diff --git a/README.md b/README.md index 29a836d..06b124d 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ Search and install almost all packages available for openSUSE and SLE: - python3-lxml - python3-termcolor +If you want to use dnf instead of zypper, you also need: +- dnf +- libdnf-repo-config-zypp + ## Install ### openSUSE Tumbleweed and Leap @@ -46,6 +50,18 @@ Output: ![Screenshot](screenshot.png) +### Using DNF instead of Zypper +If you want to, you can use [DNF](https://en.opensuse.org/SDB:DNF) instead of Zypper. +To do this, change the content of `~/.config/opi/config.json` so that it looks like this: + +```json +{ + "backend": "dnf" +} +``` + +If you want to go back to Zypper, just change the value of `backend` back to `zypp`. + ### Packages from Other Repositories **Packman Codecs** (enable you to play MP4 videos and YouTube) diff --git a/opi/__init__.py b/opi/__init__.py index ca01db1..4c1b5eb 100644 --- a/opi/__init__.py +++ b/opi/__init__.py @@ -7,6 +7,7 @@ import lxml.etree from termcolor import colored +from opi.backends import get_backend, BackendConstants OBS_APIROOT = { 'openSUSE': 'https://api.opensuse.org', @@ -72,15 +73,18 @@ def add_packman_repo(dup=False): ) if dup: - subprocess.call(['sudo', 'zypper', 'dist-upgrade', '--from', 'packman', '--allow-downgrade', '--allow-vendor-change']) + if get_backend() == BackendConstants.zypp: + subprocess.call(['sudo', 'zypper', 'dist-upgrade', '--from', 'packman', '--allow-downgrade', '--allow-vendor-change']) + elif get_backend() == BackendConstants.dnf: + subprocess.call(['sudo', 'dnf', 'dup', '--setopt=allow_vendor_change=True', '--repo', 'packman']) def install_packman_packages(packages, **kwargs): install_packages(packages, from_repo='packman', **kwargs) -############ -### ZYPP ### -############ +################ +### ZYPP/DNF ### +################ def add_repo(filename, name, url, enabled=True, gpgcheck=True, gpgkey=None, repo_type='rpm-md', auto_import_key=False, auto_refresh=False, priority=None): tf = tempfile.NamedTemporaryFile('w') @@ -101,18 +105,38 @@ def add_repo(filename, name, url, enabled=True, gpgcheck=True, gpgkey=None, repo subprocess.call(['sudo', 'cp', tf.name, '/etc/zypp/repos.d/%s.repo' % filename]) subprocess.call(['sudo', 'chmod', '644', '/etc/zypp/repos.d/%s.repo' % filename]) tf.file.close() - refresh_cmd = ['sudo', 'zypper'] - if auto_import_key: - refresh_cmd.append('--gpg-auto-import-keys') - refresh_cmd.append('ref') + refresh_cmd = [] + if get_backend() == BackendConstants.zypp: + refresh_cmd = ['sudo', 'zypper'] + if auto_import_key: + refresh_cmd.append('--gpg-auto-import-keys') + refresh_cmd.append('ref') + elif get_backend() == BackendConstants.dnf: + refresh_cmd = ['sudo', 'dnf', 'ref'] subprocess.call(refresh_cmd) -def install_packages(packages, from_repo=None, flags=None): - args = ['sudo', 'zypper', 'in'] - if from_repo: - args.extend(['--from', from_repo]) - if flags: - args.extend(flags) +def install_packages(packages, from_repo=None, allow_vendor_change=False, allow_arch_change=False, allow_downgrade=False, allow_name_change=False): + if get_backend() == BackendConstants.zypp: + args = ['sudo', 'zypper', 'in'] + if from_repo: + args.extend(['--from', from_repo]) + elif get_backend() == BackendConstants.dnf: + args = ['sudo', 'dnf', 'in'] + if from_repo: + args.extend(['--repo', from_repo]) + if get_backend() == BackendConstants.zypp: + if allow_downgrade: + args.append('--allow-downgrade') + if allow_arch_change: + args.append('--allow-arch-change') + if allow_name_change: + args.append('--allow-name-change') + if allow_vendor_change: + args.append('--allow-vendor-change') + elif get_backend() == BackendConstants.dnf: + # allow_downgrade and allow_name_change are default in DNF + if allow_vendor_change: + args.append('--setopt=allow_vendor_change=True') args.extend(packages) subprocess.call(args) @@ -248,7 +272,7 @@ def install_binary(binary): gpgcheck = True, auto_refresh = True ) - install_packages([name_with_arch], from_repo=project, flags=['--allow-vendor-change', '--allow-arch-change', '--allow-downgrade', '--allow-name-change']) + install_packages([name_with_arch], from_repo=repo_alias, allow_downgrade=True, allow_arch_change=True, allow_name_change=True, allow_vendor_change=True) ask_keep_repo(repo_alias) @@ -277,8 +301,10 @@ def ask_number(min_num, max_num, question="Choose a number (0 to quit):"): def ask_keep_repo(repo): if not ask_yes_or_no('Do you want to keep the repo "%s"?' % repo, 'y'): - subprocess.call(['sudo', 'zypper', 'rr', repo]) - + if get_backend() == BackendConstants.zypp: + subprocess.call(['sudo', 'zypper', 'rr', repo]) + if get_backend() == BackendConstants.dnf: + subprocess.call(['sudo', 'rm', '/etc/zypp/repos.d/' + repo + '.repo']) def print_package_names(package_names): i = 1 diff --git a/opi/backends/__init__.py b/opi/backends/__init__.py new file mode 100644 index 0000000..9023029 --- /dev/null +++ b/opi/backends/__init__.py @@ -0,0 +1,12 @@ +import opi.config as config + +class BackendConstants: + zypp = "zypp" + dnf = "dnf" + + +def get_backend(): + backend = config.get_key_from_config("backend") + if not backend in ["zypp", "dnf"]: + raise config.ConfigError("Invalid backend configuration.") + return backend diff --git a/opi/config/__init__.py b/opi/config/__init__.py new file mode 100644 index 0000000..a5afbd1 --- /dev/null +++ b/opi/config/__init__.py @@ -0,0 +1,34 @@ +import os +import pwd +import subprocess +import json + +cache = {} + +class ConfigError(Exception): + pass + +def create_default_config(): + path = pwd.getpwuid(os.getuid()).pw_dir + "/.config/opi/" + subprocess.call(["mkdir", "-p", path]) + config = { + "backend": "zypp" + } + config_file = open(path + 'config.json', 'w') + json.dump(config, config_file, indent=4) + +def get_key_from_config(key: str): + if not key in cache: + path = pwd.getpwuid(os.getuid()).pw_dir + "/.config/opi/config.json" + if not os.path.isfile(path): + create_default_config() + config = json.loads(open(path).read()) + cache[key] = config[key] + return cache[key] + else: + return cache[key] + +path = pwd.getpwuid(os.getuid()).pw_dir + "/.config/opi/config.json" +if not os.path.isfile(path): + create_default_config() + diff --git a/setup.py b/setup.py index a4aec3b..42f2f83 100644 --- a/setup.py +++ b/setup.py @@ -11,9 +11,9 @@ version=__version__, license='GPLv3', description='Tool to Search and install almost all packages available for openSUSE and SLE', - author='Guo Yunhe, Dominik Heidler', - author_email='i@guoyunhe.me, dheidler@suse.de', + author='Guo Yunhe, Dominik Heidler, KaratekHD', + author_email='i@guoyunhe.me, dheidler@suse.de, karatek@karatek.net', requires=['lxml', 'requests', 'termcolor'], - packages=['opi', 'opi.plugins'], + packages=['opi', 'opi.plugins', 'opi.config', 'opi.backends'], scripts=['bin/opi'], )