├── dnf ├── plugins │ ├── CMakeLists.txt │ ├── swap │ │ ├── dnf-command-swap.gresource.xml │ │ ├── swap.plugin │ │ ├── dnf-command-swap.h │ │ └── dnf-command-swap.c │ ├── clean │ │ ├── dnf-command-clean.gresource.xml │ │ ├── clean.plugin │ │ ├── dnf-command-clean.h │ │ └── dnf-command-clean.c │ ├── leaves │ │ ├── dnf-command-leaves.gresource.xml │ │ ├── leaves.plugin │ │ ├── dnf-command-leaves.h │ │ └── dnf-command-leaves.c │ ├── remove │ │ ├── dnf-command-remove.gresource.xml │ │ ├── remove.plugin │ │ ├── dnf-command-remove.h │ │ └── dnf-command-remove.c │ ├── install │ │ ├── dnf-command-install.gresource.xml │ │ ├── install.plugin │ │ ├── dnf-command-install.h │ │ └── dnf-command-install.c │ ├── upgrade │ │ ├── dnf-command-upgrade.gresource.xml │ │ ├── upgrade.plugin │ │ ├── dnf-command-upgrade.h │ │ └── dnf-command-upgrade.c │ ├── download │ │ ├── dnf-command-download.gresource.xml │ │ ├── download.plugin │ │ ├── dnf-command-download.h │ │ └── dnf-command-download.c │ ├── repolist │ │ ├── dnf-command-repolist.gresource.xml │ │ ├── repolist.plugin │ │ ├── dnf-command-repolist.h │ │ └── dnf-command-repolist.c │ ├── makecache │ │ ├── dnf-command-makecache.gresource.xml │ │ ├── makecache.plugin │ │ ├── dnf-command-makecache.h │ │ └── dnf-command-makecache.c │ ├── reinstall │ │ ├── dnf-command-reinstall.gresource.xml │ │ ├── reinstall.plugin │ │ ├── dnf-command-reinstall.h │ │ └── dnf-command-reinstall.c │ ├── repoquery │ │ ├── dnf-command-repoquery.gresource.xml │ │ ├── repoquery.plugin │ │ ├── dnf-command-repoquery.h │ │ └── dnf-command-repoquery.c │ ├── distrosync │ │ ├── dnf-command-distrosync.gresource.xml │ │ ├── distrosync.plugin │ │ ├── dnf-command-distrosync.h │ │ └── dnf-command-distrosync.c │ ├── module_reset │ │ ├── dnf-command-module_reset.gresource.xml │ │ ├── module_reset.plugin │ │ ├── dnf-command-module_reset.h │ │ └── dnf-command-module_reset.c │ ├── module_enable │ │ ├── dnf-command-module_enable.gresource.xml │ │ ├── module_enable.plugin │ │ ├── dnf-command-module_enable.h │ │ └── dnf-command-module_enable.c │ └── module_disable │ │ ├── dnf-command-module_disable.gresource.xml │ │ ├── module_disable.plugin │ │ ├── dnf-command-module_disable.h │ │ └── dnf-command-module_disable.c ├── dnf-utils.h ├── dnf-command.c ├── dnf-command.h ├── meson.build ├── CMakeLists.txt ├── dnf-utils.c └── dnf-main.c ├── .packit.yaml ├── .tito ├── tito.props └── packages │ └── .readme ├── .git-commit-template ├── microdnf.spec ├── CMakeLists.txt ├── cmake └── GResource.cmake ├── meson.build ├── README.md └── COPYING /dnf/plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.packit.yaml: -------------------------------------------------------------------------------- 1 | # See the documentation for more information: 2 | # https://packit.dev/docs/configuration 3 | 4 | # To disable default jobs set them as empty 5 | jobs: [] 6 | -------------------------------------------------------------------------------- /.tito/tito.props: -------------------------------------------------------------------------------- 1 | [buildconfig] 2 | builder = tito.builder.Builder 3 | tagger = tito.tagger.VersionTagger 4 | changelog_do_not_remove_cherrypick = 0 5 | changelog_format = %s (%ae) 6 | -------------------------------------------------------------------------------- /.tito/packages/.readme: -------------------------------------------------------------------------------- 1 | the .tito/packages directory contains metadata files 2 | named after their packages. Each file has the latest tagged 3 | version and the project's relative directory. 4 | -------------------------------------------------------------------------------- /dnf/plugins/swap/dnf-command-swap.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | swap.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/clean/dnf-command-clean.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | clean.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/leaves/dnf-command-leaves.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | leaves.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/remove/dnf-command-remove.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | remove.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/install/dnf-command-install.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | install.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/upgrade/dnf-command-upgrade.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | upgrade.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/download/dnf-command-download.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | download.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/repolist/dnf-command-repolist.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | repolist.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/makecache/dnf-command-makecache.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | makecache.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/reinstall/dnf-command-reinstall.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | reinstall.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/repoquery/dnf-command-repoquery.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | repoquery.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/distrosync/dnf-command-distrosync.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | distrosync.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/module_reset/dnf-command-module_reset.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | module_reset.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/module_enable/dnf-command-module_enable.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | module_enable.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/module_disable/dnf-command-module_disable.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | module_disable.plugin 5 | 6 | 7 | -------------------------------------------------------------------------------- /dnf/plugins/clean/clean.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_clean 3 | Embedded = dnf_command_clean_register_types 4 | Name = clean 5 | Description = Remove cached data 6 | Authors = Jaroslav Rohel 7 | License = GPL-2.0+ 8 | Copyright = Copyright © 2017 Jaroslav Rohel 9 | X-Command-Syntax = clean all 10 | -------------------------------------------------------------------------------- /dnf/plugins/remove/remove.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_remove 3 | Embedded = dnf_command_remove_register_types 4 | Name = remove 5 | Description = Remove packages 6 | Authors = Igor Gnatenko 7 | License = GPL-2.0+ 8 | Copyright = Copyright © 2016 Igor Gnatenko 9 | X-Command-Syntax = remove PACKAGE [PACKAGE…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/makecache/makecache.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_makecache 3 | Embedded = dnf_command_makecache_register_types 4 | Name = makecache 5 | Description = Generate the metadata cache 6 | Authors = Jaroslav Rohel 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2021 Red Hat, Inc. 9 | X-Command-Syntax = makecache 10 | -------------------------------------------------------------------------------- /dnf/plugins/reinstall/reinstall.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_reinstall 3 | Embedded = dnf_command_reinstall_register_types 4 | Name = reinstall 5 | Description = Reinstall packages 6 | Authors = Jaroslav Rohel 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2019 Red Hat, Inc. 9 | X-Command-Syntax = reinstall PACKAGE [PACKAGE…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/download/download.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_download 3 | Embedded = dnf_command_download_register_types 4 | Name = download 5 | Description = Download packages 6 | Authors = Daniel Hams 7 | License = GPL-2.0+ 8 | Copyright = Copyright © 2020-2021 Daniel Hams 9 | X-Command-Syntax = download [OPTION…] PACKAGE [PACKAGE…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/repolist/repolist.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_repolist 3 | Embedded = dnf_command_repolist_register_types 4 | Name = repolist 5 | Description = List repositories 6 | Authors = Jaroslav Rohel 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2019 Red Hat, Inc. 9 | X-Command-Syntax = repolist [--all] [--disabled] [--enabled] 10 | -------------------------------------------------------------------------------- /dnf/plugins/repoquery/repoquery.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_repoquery 3 | Embedded = dnf_command_repoquery_register_types 4 | Name = repoquery 5 | Description = Search for packages matching keyword 6 | Authors = Jaroslav Rohel 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2019 Red Hat, Inc. 9 | X-Command-Syntax = repoquery [OPTION…] [KEY…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/leaves/leaves.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_leaves 3 | Embedded = dnf_command_leaves_register_types 4 | Name = leaves 5 | Description = List installed packages not required by other installed packages 6 | Authors = Emil Renner Berthing 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2022 Emil Renner Berthing 9 | X-Command-Syntax = leaves 10 | -------------------------------------------------------------------------------- /dnf/plugins/swap/swap.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_swap 3 | Embedded = dnf_command_swap_register_types 4 | Name = swap 5 | Description = Removes package and installs another in one transaction 6 | Authors = Jaroslav Rohel 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2022 Red Hat, Inc. 9 | X-Command-Syntax = swap PACKAGE_TO_REMOVE PACKAGE_TO_INSTALL 10 | -------------------------------------------------------------------------------- /dnf/plugins/module_reset/module_reset.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_module_reset 3 | Embedded = dnf_command_module_reset_register_types 4 | Name = module_reset 5 | Description = Reset a module stream 6 | Authors = Jaroslav Mracek 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2020 Red Hat, Inc. 9 | X-Command-Syntax = module reset module-spec [module-spec…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/module_enable/module_enable.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_module_enable 3 | Embedded = dnf_command_module_enable_register_types 4 | Name = module_enable 5 | Description = Enable a module stream 6 | Authors = Jaroslav Rohel 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2020 Red Hat, Inc. 9 | X-Command-Syntax = module enable module-spec [module-spec…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/module_disable/module_disable.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_module_disable 3 | Embedded = dnf_command_module_disable_register_types 4 | Name = module_disable 5 | Description = Disable a module stream 6 | Authors = Jaroslav Mracek 7 | License = GPL-2.0+ 8 | Copyright = Copyright (C) 2020 Red Hat, Inc. 9 | X-Command-Syntax = module disable module-spec [module-spec…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/upgrade/upgrade.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_upgrade 3 | Embedded = dnf_command_upgrade_register_types 4 | Name = upgrade 5 | Description = Upgrade packages 6 | Authors = Igor Gnatenko 7 | License = GPL-2.0+ 8 | Copyright = Copyright © 2016 Igor Gnatenko 9 | X-Command-Syntax = upgrade [PACKAGE…] 10 | X-Alias-Name = update 11 | X-Alias-Description = Compatibility alias for the "upgrade" command 12 | -------------------------------------------------------------------------------- /dnf/plugins/install/install.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_install 3 | Embedded = dnf_command_install_register_types 4 | Name = install 5 | Description = Install packages 6 | Authors = Richard Hughes , Colin Walters , Igor Gnatenko 7 | License = GPL-2.0+ 8 | Copyright = Copyright © 2010-2016 Richard Hughes, Colin Walters, Igor Gnatenko 9 | X-Command-Syntax = install PACKAGE [PACKAGE…] 10 | -------------------------------------------------------------------------------- /dnf/plugins/distrosync/distrosync.plugin: -------------------------------------------------------------------------------- 1 | [Plugin] 2 | Module = command_distro-sync 3 | Embedded = dnf_command_distrosync_register_types 4 | Name = distro-sync 5 | Description = Upgrade/downgrade packages to match versions in repositories 6 | Authors = Neal Gompa 7 | License = GPL-2.0+ 8 | Copyright = Copyright © 2021 Neal Gompa 9 | X-Command-Syntax = distro-sync [PACKAGE…] 10 | X-Alias-Name = dsync 11 | X-Alias-Description = Compatibility alias for the "distro-sync" command 12 | -------------------------------------------------------------------------------- /.git-commit-template: -------------------------------------------------------------------------------- 1 | 2 | 3 | # In addition to regular commit message, you can uncomment and fill in the 4 | # following to include this change in the released RPM package changelog: 5 | 6 | # = changelog = 7 | # msg: 8 | # type: 9 | # resolves: 10 | # related: 11 | 12 | # msg = message to be included in the changelog 13 | # type = one of: bugfix/enhancement/security 14 | # resolves = URLs to bugs or issues resolved by this commit 15 | # related = URLs to any related bugs or issues 16 | 17 | -------------------------------------------------------------------------------- /dnf/dnf-utils.h: -------------------------------------------------------------------------------- 1 | /* dnf-utils.h 2 | * 3 | * Copyright © 2016 Colin Walters 4 | * Copyright © 2016-2017 Igor Gnatenko 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | gboolean dnf_utils_print_transaction (DnfContext *ctx); 28 | gboolean dnf_utils_conf_main_get_bool_opt (const gchar *name, enum DnfConfPriority *priority); 29 | gboolean dnf_utils_userconfirm (void); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/swap/dnf-command-swap.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-swap.h 2 | * 3 | * Copyright (C) 2022 Red Hat, Inc. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_SWAP dnf_command_swap_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandSwap, dnf_command_swap, DNF, COMMAND_SWAP, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_swap_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/clean/dnf-command-clean.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-clean.h 2 | * 3 | * Copyright © 2017 Jaroslav Rohel 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_CLEAN dnf_command_clean_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandClean, dnf_command_clean, DNF, COMMAND_CLEAN, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_clean_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/leaves/dnf-command-leaves.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-leaves.h 2 | * 3 | * Copyright © 2022 Emil Renner Berthing 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_LEAVES dnf_command_leaves_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandLeaves, dnf_command_leaves, DNF, COMMAND_LEAVES, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_leaves_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/remove/dnf-command-remove.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-remove.h 2 | * 3 | * Copyright © 2016 Igor Gnatenko 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_REMOVE dnf_command_remove_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandRemove, dnf_command_remove, DNF, COMMAND_REMOVE, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_remove_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/install/dnf-command-install.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-install.h 2 | * 3 | * Copyright © 2016 Igor Gnatenko 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_INSTALL dnf_command_install_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandInstall, dnf_command_install, DNF, COMMAND_INSTALL, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_install_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/makecache/dnf-command-makecache.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-makecache.h 2 | * 3 | * Copyright (C) 2021 Red Hat, Inc. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_MAKECACHE dnf_command_makecache_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandMakecache, dnf_command_makecache, DNF, COMMAND_MAKECACHE, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_makecache_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/upgrade/dnf-command-upgrade.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-upgrade.h 2 | * 3 | * Copyright © 2016 Igor Gnatenko 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_UPGRADE dnf_command_upgrade_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandUpgrade, dnf_command_upgrade, DNF, COMMAND_UPGRADE, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_upgrade_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/download/dnf-command-download.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-download.h 2 | * 3 | * Copyright © 2020-2021 Daniel Hams 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_DOWNLOAD dnf_command_download_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandDownload, dnf_command_download, DNF, COMMAND_DOWNLOAD, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_download_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/distrosync/dnf-command-distrosync.h: -------------------------------------------------------------------------------- 1 | /* dnf-command-distrosync.h 2 | * 3 | * Copyright © 2021 Neal Gompa 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include "dnf-command.h" 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND_DISTROSYNC dnf_command_distrosync_get_type () 27 | G_DECLARE_FINAL_TYPE (DnfCommandDistroSync, dnf_command_distrosync, DNF, COMMAND_DISTROSYNC, PeasExtensionBase) 28 | 29 | G_MODULE_EXPORT void dnf_command_distrosync_register_types (PeasObjectModule *module); 30 | 31 | G_END_DECLS 32 | -------------------------------------------------------------------------------- /dnf/plugins/repolist/dnf-command-repolist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "dnf-command.h" 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define DNF_TYPE_COMMAND_REPOLIST dnf_command_repolist_get_type () 29 | G_DECLARE_FINAL_TYPE (DnfCommandRepolist, dnf_command_repolist, DNF, COMMAND_REPOLIST, PeasExtensionBase) 30 | 31 | G_MODULE_EXPORT void dnf_command_repolist_register_types (PeasObjectModule *module); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /dnf/plugins/reinstall/dnf-command-reinstall.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "dnf-command.h" 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define DNF_TYPE_COMMAND_REINSTALL dnf_command_reinstall_get_type () 29 | G_DECLARE_FINAL_TYPE (DnfCommandReinstall, dnf_command_reinstall, DNF, COMMAND_REINSTALL, PeasExtensionBase) 30 | 31 | G_MODULE_EXPORT void dnf_command_reinstall_register_types (PeasObjectModule *module); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /dnf/plugins/repoquery/dnf-command-repoquery.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "dnf-command.h" 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define DNF_TYPE_COMMAND_REPOQUERY dnf_command_repoquery_get_type () 29 | G_DECLARE_FINAL_TYPE (DnfCommandRepoquery, dnf_command_repoquery, DNF, COMMAND_REPOQUERY, PeasExtensionBase) 30 | 31 | G_MODULE_EXPORT void dnf_command_repoquery_register_types (PeasObjectModule *module); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /dnf/plugins/module_reset/dnf-command-module_reset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "dnf-command.h" 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define DNF_TYPE_COMMAND_MODULE_RESET dnf_command_module_reset_get_type () 29 | G_DECLARE_FINAL_TYPE (DnfCommandModuleReset, dnf_command_module_reset, DNF, COMMAND_MODULE_RESET, PeasExtensionBase) 30 | 31 | G_MODULE_EXPORT void dnf_command_module_reset_register_types (PeasObjectModule *module); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /dnf/plugins/module_enable/dnf-command-module_enable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "dnf-command.h" 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define DNF_TYPE_COMMAND_MODULE_ENABLE dnf_command_module_enable_get_type () 29 | G_DECLARE_FINAL_TYPE (DnfCommandModuleEnable, dnf_command_module_enable, DNF, COMMAND_MODULE_ENABLE, PeasExtensionBase) 30 | 31 | G_MODULE_EXPORT void dnf_command_module_enable_register_types (PeasObjectModule *module); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /dnf/plugins/module_disable/dnf-command-module_disable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "dnf-command.h" 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define DNF_TYPE_COMMAND_MODULE_DISABLE dnf_command_module_disable_get_type () 29 | G_DECLARE_FINAL_TYPE (DnfCommandModuleDisable, dnf_command_module_disable, DNF, COMMAND_MODULE_DISABLE, PeasExtensionBase) 30 | 31 | G_MODULE_EXPORT void dnf_command_module_disable_register_types (PeasObjectModule *module); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /dnf/dnf-command.c: -------------------------------------------------------------------------------- 1 | /* dnf-command.c 2 | * 3 | * Copyright © 2016 Igor Gnatenko 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command.h" 20 | 21 | G_DEFINE_INTERFACE (DnfCommand, dnf_command, G_TYPE_OBJECT) 22 | 23 | static void 24 | dnf_command_default_init (DnfCommandInterface *iface) 25 | { 26 | } 27 | 28 | gboolean 29 | dnf_command_run (DnfCommand *cmd, 30 | int argc, 31 | char *argv[], 32 | GOptionContext *opt_ctx, 33 | DnfContext *ctx, 34 | GError **error) 35 | { 36 | g_return_val_if_fail (DNF_IS_COMMAND (cmd), FALSE); 37 | 38 | DnfCommandInterface *iface = DNF_COMMAND_GET_IFACE (cmd); 39 | g_return_val_if_fail (iface->run, TRUE); 40 | return iface->run (cmd, argc, argv, opt_ctx, ctx, error); 41 | } 42 | -------------------------------------------------------------------------------- /microdnf.spec: -------------------------------------------------------------------------------- 1 | %global libdnf_version 0.62.0 2 | 3 | Name: microdnf 4 | Version: 3.10.2 5 | Release: 1%{?dist} 6 | Summary: Lightweight implementation of DNF in C 7 | 8 | License: GPL-2.0-or-later 9 | URL: https://github.com/rpm-software-management/microdnf 10 | Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz 11 | 12 | BuildRequires: gcc 13 | BuildRequires: meson >= 0.36.0 14 | BuildRequires: pkgconfig(glib-2.0) >= 2.44.0 15 | BuildRequires: pkgconfig(gobject-2.0) >= 2.44.0 16 | BuildRequires: pkgconfig(libpeas-1.0) >= 1.20.0 17 | BuildRequires: (pkgconfig(libdnf) >= %{libdnf_version} with pkgconfig(libdnf) < 5) 18 | BuildRequires: pkgconfig(smartcols) 19 | BuildRequires: help2man 20 | 21 | Requires: libdnf%{?_isa} >= %{libdnf_version} 22 | %if 0%{?rhel} > 8 || 0%{?fedora} 23 | # Ensure DNF package manager configuration skeleton is installed 24 | Requires: /etc/dnf/dnf.conf 25 | %endif 26 | 27 | %description 28 | Micro DNF is a lightweight C implementation of DNF, designed to be used 29 | for doing simple packaging actions when you don't need full-blown DNF and 30 | you want the tiniest useful environments possible. 31 | 32 | That is, you don't want any interpreter stack and you want the most 33 | minimal environment possible so you can build up to exactly what you need. 34 | 35 | 36 | %prep 37 | %autosetup -p1 38 | 39 | %build 40 | %meson 41 | %meson_build 42 | 43 | %install 44 | %meson_install 45 | 46 | %check 47 | %meson_test 48 | 49 | %files 50 | %license COPYING 51 | %doc README.md 52 | %{_mandir}/man8/microdnf.8* 53 | %{_bindir}/%{name} 54 | 55 | %changelog 56 | -------------------------------------------------------------------------------- /dnf/dnf-command.h: -------------------------------------------------------------------------------- 1 | /* dnf-command.h 2 | * 3 | * Copyright © 2016 Igor Gnatenko 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #pragma once 20 | 21 | #include 22 | #include 23 | 24 | G_BEGIN_DECLS 25 | 26 | #define DNF_TYPE_COMMAND dnf_command_get_type () 27 | G_DECLARE_INTERFACE (DnfCommand, dnf_command, DNF, COMMAND, GObject) 28 | 29 | struct _DnfCommandInterface 30 | { 31 | GTypeInterface parent_iface; 32 | 33 | gboolean (*run) (DnfCommand *cmd, 34 | int argc, 35 | char *argv[], 36 | GOptionContext *opt_ctx, 37 | DnfContext *ctx, 38 | GError **error); 39 | }; 40 | 41 | gboolean dnf_command_run (DnfCommand *cmd, 42 | int argc, 43 | char *argv[], 44 | GOptionContext *opt_ctx, 45 | DnfContext *ctx, 46 | GError **error); 47 | 48 | G_END_DECLS 49 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.5) 2 | project (microdnf C) 3 | set (PROJECT_VERSION 3.10.2) 4 | 5 | list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) 6 | 7 | include (CheckCCompilerFlag) 8 | include (GNUInstallDirs) 9 | include (GResource) 10 | 11 | check_c_compiler_flag ("--std=gnu11" SUPPORT_GNU11_STD) 12 | if (NOT SUPPORT_GNU11_STD) 13 | message (FATAL_ERROR "Support for --std=gnu11 is mandatory") 14 | endif () 15 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --std=gnu11") 16 | 17 | find_package (PkgConfig REQUIRED) 18 | pkg_check_modules (GLIB REQUIRED glib-2.0>=2.44.0) 19 | pkg_check_modules (GOBJECT REQUIRED gobject-2.0>=2.44.0) 20 | pkg_check_modules (PEAS REQUIRED libpeas-1.0>=1.20.0) 21 | pkg_check_modules (LIBDNF REQUIRED libdnf>=0.62.0) 22 | pkg_check_modules (SCOLS REQUIRED smartcols) 23 | 24 | set (PKG_LIBDIR ${CMAKE_INSTALL_FULL_LIBDIR}/dnf) 25 | set (PKG_DATADIR ${CMAKE_INSTALL_FULL_DATADIR}/dnf) 26 | add_definitions (-DPACKAGE_LIBDIR="${PKG_LIBDIR}") 27 | add_definitions (-DPACKAGE_DATADIR="${PKG_DATADIR}") 28 | 29 | find_file (HELP2MAN_EXECUTABLE help2man) 30 | if (NOT HELP2MAN_EXECUTABLE) 31 | message (FATAL_ERROR "unable to find help2man") 32 | endif () 33 | 34 | set (MANPAGE ${CMAKE_CURRENT_BINARY_DIR}/microdnf.8) 35 | add_custom_command ( 36 | DEPENDS microdnf 37 | OUTPUT ${MANPAGE} 38 | COMMAND ${HELP2MAN_EXECUTABLE} $ 39 | --version-string=${PROJECT_VERSION} 40 | --no-info 41 | --section=8 42 | --name="Micro DNF" 43 | --output=${MANPAGE} 44 | ) 45 | add_custom_target (manpage ALL DEPENDS ${MANPAGE}) 46 | install (FILES ${MANPAGE} DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man8) 47 | 48 | include_directories (${GLIB_INCLUDE_DIRS}) 49 | include_directories (${GOBJECT_INCLUDE_DIRS}) 50 | include_directories (${PEAS_INCLUDE_DIRS}) 51 | include_directories (${LIBDNF_INCLUDE_DIRS}) 52 | include_directories (${SCOLS_INCLUDE_DIRS}) 53 | 54 | add_subdirectory (dnf) 55 | -------------------------------------------------------------------------------- /cmake/GResource.cmake: -------------------------------------------------------------------------------- 1 | find_program (GLIB_COMPILE_RESOURCES_EXECUTABLE glib-compile-resources) 2 | mark_as_advanced (GLIB_COMPILE_RESOURCES_EXECUTABLE) 3 | 4 | include (CMakeParseArguments) 5 | 6 | function (GLIB_COMPILE_RESOURCES output_var input) 7 | cmake_parse_arguments ( 8 | ARGS 9 | "MANUAL_REGISTER;INTERNAL" 10 | "C_PREFIX" 11 | "DATA_DIR" 12 | ${ARGN}) 13 | 14 | set (in_file ${CMAKE_CURRENT_SOURCE_DIR}/${input}) 15 | get_filename_component (WORKING_DIR ${in_file} PATH) 16 | string (REGEX REPLACE "\\.xml" ".c" input ${input}) 17 | set (out_file "${CMAKE_CURRENT_BINARY_DIR}/${input}") 18 | get_filename_component (OUTPUT_DIR ${out_file} PATH) 19 | file (MAKE_DIRECTORY ${OUTPUT_DIR}) 20 | 21 | execute_process ( 22 | COMMAND 23 | ${GLIB_COMPILE_RESOURCES_EXECUTABLE} 24 | --generate-dependencies 25 | ${in_file} 26 | WORKING_DIRECTORY ${WORKING_DIR} 27 | OUTPUT_VARIABLE in_file_dep) 28 | string (REGEX REPLACE "\r?\n$" ";" in_file_dep "${in_file_dep}") 29 | set (in_file_dep_path "") 30 | foreach (dep ${in_file_dep}) 31 | list (APPEND in_file_dep_path "${WORKING_DIR}/${dep}") 32 | endforeach () 33 | 34 | set (additional_args "") 35 | if (ARGS_MANUAL_REGISTER) 36 | list (APPEND additional_args "--manual-register") 37 | endif () 38 | if (ARGS_INTERNAL) 39 | list (APPEND additional_args "--internal") 40 | endif () 41 | if (ARGS_C_PREFIX) 42 | list (APPEND additional_args "--c-name=${ARGS_C_PREFIX}") 43 | endif () 44 | add_custom_command ( 45 | OUTPUT ${out_file} 46 | WORKING_DIRECTORY ${WORKING_DIR} 47 | COMMAND 48 | ${GLIB_COMPILE_RESOURCES_EXECUTABLE} 49 | ARGS 50 | "--generate-source" 51 | "--target=${out_file}" 52 | ${additional_args} 53 | ${in_file} 54 | DEPENDS 55 | ${in_file};${in_file_dep_path}) 56 | set (${output_var} ${out_file} PARENT_SCOPE) 57 | endfunction () 58 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('microdnf', 'c', 2 | version : '3.10.2', 3 | license : 'GPL-2.0+', 4 | default_options : [ 5 | 'b_asneeded=True', 6 | 'b_lundef=True', 7 | 'c_std=gnu11', 8 | 'warning_level=1', 9 | ], 10 | meson_version : '>=0.36.0') 11 | 12 | cc = meson.get_compiler('c') 13 | test_cflags = [ 14 | '-fstrict-aliasing', 15 | '-Wformat=2', 16 | '-Wunused', 17 | '-Wuninitialized', 18 | '-Wstrict-prototypes', 19 | '-Wmissing-prototypes', 20 | '-Werror=implicit', 21 | '-Werror=init-self', 22 | '-Werror=main', 23 | ] 24 | foreach cflag : test_cflags 25 | if cc.has_argument(cflag) 26 | add_project_arguments(cflag, language : 'c') 27 | endif 28 | endforeach 29 | 30 | gnome = import('gnome') 31 | 32 | glib = dependency('glib-2.0', version : '>=2.44.0') 33 | gobject = dependency('gobject-2.0', version : '>=2.44.0') 34 | libpeas = dependency('libpeas-1.0', version : '>=1.20.0') 35 | libdnf = dependency('libdnf', version : '>=0.62.0') 36 | scols = dependency('smartcols') 37 | 38 | pkg_libdir = join_paths(get_option('prefix'), get_option('libdir'), 'dnf') 39 | pkg_datadir = join_paths(get_option('prefix'), get_option('datadir'), 'dnf') 40 | add_project_arguments( 41 | '-DPACKAGE_LIBDIR="@0@"'.format(pkg_libdir), 42 | '-DPACKAGE_DATADIR="@0@"'.format(pkg_datadir), 43 | language : 'c', 44 | ) 45 | 46 | subdir('dnf') 47 | 48 | help2man = find_program('help2man', required: true) 49 | if help2man.found() 50 | help2man_opts = [ 51 | '--version-string=' + meson.project_version(), 52 | '--no-info', 53 | '--section=8', 54 | '--name=Micro DNF', 55 | ] 56 | 57 | custom_target('microdnf.8', 58 | output: 'microdnf.8', 59 | command: [ 60 | help2man, help2man_opts, '--output=@OUTPUT@', microdnf 61 | ], 62 | install: true, 63 | install_dir: get_option('mandir') + '/man8', 64 | ) 65 | endif 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | microdnf 2 | ======== 3 | 4 | A minimal `dnf` for (mostly) Docker containers that uses 5 | [libdnf](https://github.com/rpm-software-management/libdnf) 6 | and hence doesn't require Python. 7 | 8 | This project was inspired by and derived from 9 | https://github.com/cgwalters/micro-yuminst 10 | 11 | 12 | Reporting issues 13 | ================ 14 | 15 | * [Red Hat Bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=microdnf) is the preferred way of filing issues. [[backlog](https://bugzilla.redhat.com/buglist.cgi?bug_status=__open__&product=Fedora&component=microdnf)] 16 | * [GitHub issues](https://github.com/rpm-software-management/microdnf/issues/new) are also accepted. [[backlog](https://github.com/rpm-software-management/microdnf/issues)] 17 | 18 | 19 | Contribution 20 | ============ 21 | 22 | Here's the most direct way to get your work merged into the project. 23 | 24 | 1. Fork the project 25 | 1. Clone down your fork 26 | 1. Implement your feature or bug fix and commit changes 27 | 1. If the change fixes a bug at [Red Hat bugzilla](https://bugzilla.redhat.com/), or if it is important to the end user, add the following block to the commit message: 28 | 29 | = changelog = 30 | msg: message to be included in the changelog 31 | type: one of: bugfix/enhancement/security (this field is required when message is present) 32 | resolves: URLs to bugs or issues resolved by this commit (can be specified multiple times) 33 | related: URLs to any related bugs or issues (can be specified multiple times) 34 | 35 | * For example:: 36 | 37 | = changelog = 38 | msg: Don't print lines with (null) in transaction report 39 | type: bugfix 40 | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1691353 41 | 42 | * For your convenience, you can also use git commit template by running the following command in the top-level directory of this project: 43 | 44 | git config commit.template ./.git-commit-template 45 | 46 | 1. Push the branch to your fork 47 | 1. Send a pull request for your branch 48 | 49 | -------------------------------------------------------------------------------- /dnf/plugins/makecache/dnf-command-makecache.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-makecache.c 2 | * 3 | * Copyright (C) 2021 Red Hat, Inc. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command-makecache.h" 20 | 21 | struct _DnfCommandMakecache 22 | { 23 | PeasExtensionBase parent_instance; 24 | }; 25 | 26 | static void dnf_command_makecache_iface_init (DnfCommandInterface *iface); 27 | 28 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandMakecache, 29 | dnf_command_makecache, 30 | PEAS_TYPE_EXTENSION_BASE, 31 | 0, 32 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 33 | dnf_command_makecache_iface_init)) 34 | 35 | static void 36 | dnf_command_makecache_init (DnfCommandMakecache *self) 37 | { 38 | } 39 | 40 | static gboolean 41 | dnf_command_makecache_run (DnfCommand *cmd, 42 | int argc, 43 | char *argv[], 44 | GOptionContext *opt_ctx, 45 | DnfContext *ctx, 46 | GError **error) 47 | { 48 | const GOptionEntry opts[] = { 49 | { NULL } 50 | }; 51 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 52 | 53 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 54 | return FALSE; 55 | 56 | if (argc > 1) 57 | { 58 | g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION, "Unknown argument %s", argv[1]); 59 | return FALSE; 60 | } 61 | 62 | DnfState * state = dnf_context_get_state (ctx); 63 | DnfContextSetupSackFlags sack_flags = DNF_CONTEXT_SETUP_SACK_FLAG_SKIP_RPMDB; 64 | if (!dnf_context_setup_sack_with_flags (ctx, state, sack_flags, error)) { 65 | return FALSE; 66 | } 67 | 68 | g_print ("Metadata cache created.\n"); 69 | 70 | return TRUE; 71 | } 72 | 73 | static void 74 | dnf_command_makecache_class_init (DnfCommandMakecacheClass *klass) 75 | { 76 | } 77 | 78 | static void 79 | dnf_command_makecache_iface_init (DnfCommandInterface *iface) 80 | { 81 | iface->run = dnf_command_makecache_run; 82 | } 83 | 84 | static void 85 | dnf_command_makecache_class_finalize (DnfCommandMakecacheClass *klass) 86 | { 87 | } 88 | 89 | G_MODULE_EXPORT void 90 | dnf_command_makecache_register_types (PeasObjectModule *module) 91 | { 92 | dnf_command_makecache_register_type (G_TYPE_MODULE (module)); 93 | 94 | peas_object_module_register_extension_type (module, 95 | DNF_TYPE_COMMAND, 96 | DNF_TYPE_COMMAND_MAKECACHE); 97 | } 98 | -------------------------------------------------------------------------------- /dnf/plugins/upgrade/dnf-command-upgrade.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-upgrade.c 2 | * 3 | * Copyright © 2016-2017 Igor Gnatenko 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command-upgrade.h" 20 | #include "dnf-utils.h" 21 | 22 | struct _DnfCommandUpgrade 23 | { 24 | PeasExtensionBase parent_instance; 25 | }; 26 | 27 | static void dnf_command_upgrade_iface_init (DnfCommandInterface *iface); 28 | 29 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandUpgrade, 30 | dnf_command_upgrade, 31 | PEAS_TYPE_EXTENSION_BASE, 32 | 0, 33 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 34 | dnf_command_upgrade_iface_init)) 35 | 36 | static void 37 | dnf_command_upgrade_init (DnfCommandUpgrade *self) 38 | { 39 | } 40 | 41 | static gboolean 42 | dnf_command_upgrade_run (DnfCommand *cmd, 43 | int argc, 44 | char *argv[], 45 | GOptionContext *opt_ctx, 46 | DnfContext *ctx, 47 | GError **error) 48 | { 49 | g_auto(GStrv) pkgs = NULL; 50 | const GOptionEntry opts[] = { 51 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 52 | { NULL } 53 | }; 54 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 55 | 56 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 57 | return FALSE; 58 | 59 | if (pkgs == NULL) 60 | { 61 | if (!dnf_context_update_all (ctx, error)) 62 | return FALSE; 63 | } 64 | else 65 | { 66 | /* Upgrade each package */ 67 | for (GStrv pkg = pkgs; *pkg != NULL; pkg++) 68 | { 69 | if (!dnf_context_update (ctx, *pkg, error)) 70 | return FALSE; 71 | } 72 | } 73 | DnfGoalActions flags = 0; 74 | if (dnf_context_get_best()) 75 | { 76 | flags |= DNF_FORCE_BEST; 77 | } 78 | if (!dnf_context_get_install_weak_deps ()) 79 | flags |= DNF_IGNORE_WEAK_DEPS; 80 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), flags, error)) 81 | return FALSE; 82 | if (!dnf_utils_print_transaction (ctx)) 83 | return TRUE; 84 | if (!dnf_utils_userconfirm ()) 85 | return FALSE; 86 | if (!dnf_context_run (ctx, NULL, error)) 87 | return FALSE; 88 | g_print ("Complete.\n"); 89 | 90 | return TRUE; 91 | } 92 | 93 | static void 94 | dnf_command_upgrade_class_init (DnfCommandUpgradeClass *klass) 95 | { 96 | } 97 | 98 | static void 99 | dnf_command_upgrade_iface_init (DnfCommandInterface *iface) 100 | { 101 | iface->run = dnf_command_upgrade_run; 102 | } 103 | 104 | static void 105 | dnf_command_upgrade_class_finalize (DnfCommandUpgradeClass *klass) 106 | { 107 | } 108 | 109 | G_MODULE_EXPORT void 110 | dnf_command_upgrade_register_types (PeasObjectModule *module) 111 | { 112 | dnf_command_upgrade_register_type (G_TYPE_MODULE (module)); 113 | 114 | peas_object_module_register_extension_type (module, 115 | DNF_TYPE_COMMAND, 116 | DNF_TYPE_COMMAND_UPGRADE); 117 | } 118 | -------------------------------------------------------------------------------- /dnf/plugins/distrosync/dnf-command-distrosync.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-distrosync.c 2 | * 3 | * Copyright © 2021 Neal Gompa 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command-distrosync.h" 20 | #include "dnf-utils.h" 21 | 22 | struct _DnfCommandDistroSync 23 | { 24 | PeasExtensionBase parent_instance; 25 | }; 26 | 27 | static void dnf_command_distrosync_iface_init (DnfCommandInterface *iface); 28 | 29 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandDistroSync, 30 | dnf_command_distrosync, 31 | PEAS_TYPE_EXTENSION_BASE, 32 | 0, 33 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 34 | dnf_command_distrosync_iface_init)) 35 | 36 | static void 37 | dnf_command_distrosync_init (DnfCommandDistroSync *self) 38 | { 39 | } 40 | 41 | static gboolean 42 | dnf_command_distrosync_run (DnfCommand *cmd, 43 | int argc, 44 | char *argv[], 45 | GOptionContext *opt_ctx, 46 | DnfContext *ctx, 47 | GError **error) 48 | { 49 | g_auto(GStrv) pkgs = NULL; 50 | const GOptionEntry opts[] = { 51 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 52 | { NULL } 53 | }; 54 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 55 | 56 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 57 | return FALSE; 58 | 59 | if (pkgs == NULL) 60 | { 61 | if (!dnf_context_distrosync_all (ctx, error)) 62 | return FALSE; 63 | } 64 | else 65 | { 66 | /* Sync each package */ 67 | for (GStrv pkg = pkgs; *pkg != NULL; pkg++) 68 | { 69 | if (!dnf_context_distrosync (ctx, *pkg, error)) 70 | return FALSE; 71 | } 72 | } 73 | DnfGoalActions flags = 0; 74 | if (dnf_context_get_best()) 75 | { 76 | flags |= DNF_FORCE_BEST; 77 | } 78 | if (!dnf_context_get_install_weak_deps ()) 79 | flags |= DNF_IGNORE_WEAK_DEPS; 80 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), flags, error)) 81 | return FALSE; 82 | if (!dnf_utils_print_transaction (ctx)) 83 | return TRUE; 84 | if (!dnf_utils_userconfirm ()) 85 | return FALSE; 86 | if (!dnf_context_run (ctx, NULL, error)) 87 | return FALSE; 88 | g_print ("Complete.\n"); 89 | 90 | return TRUE; 91 | } 92 | 93 | static void 94 | dnf_command_distrosync_class_init (DnfCommandDistroSyncClass *klass) 95 | { 96 | } 97 | 98 | static void 99 | dnf_command_distrosync_iface_init (DnfCommandInterface *iface) 100 | { 101 | iface->run = dnf_command_distrosync_run; 102 | } 103 | 104 | static void 105 | dnf_command_distrosync_class_finalize (DnfCommandDistroSyncClass *klass) 106 | { 107 | } 108 | 109 | G_MODULE_EXPORT void 110 | dnf_command_distrosync_register_types (PeasObjectModule *module) 111 | { 112 | dnf_command_distrosync_register_type (G_TYPE_MODULE (module)); 113 | 114 | peas_object_module_register_extension_type (module, 115 | DNF_TYPE_COMMAND, 116 | DNF_TYPE_COMMAND_DISTROSYNC); 117 | } 118 | -------------------------------------------------------------------------------- /dnf/plugins/remove/dnf-command-remove.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-remove.c 2 | * 3 | * Copyright © 2016 Igor Gnatenko 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command-remove.h" 20 | #include "dnf-utils.h" 21 | 22 | struct _DnfCommandRemove 23 | { 24 | PeasExtensionBase parent_instance; 25 | }; 26 | 27 | static void dnf_command_remove_iface_init (DnfCommandInterface *iface); 28 | 29 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandRemove, 30 | dnf_command_remove, 31 | PEAS_TYPE_EXTENSION_BASE, 32 | 0, 33 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 34 | dnf_command_remove_iface_init)) 35 | 36 | static void 37 | dnf_command_remove_init (DnfCommandRemove *self) 38 | { 39 | } 40 | 41 | static void 42 | disable_available_repos (DnfContext *ctx) 43 | { 44 | GPtrArray *repos = dnf_context_get_repos (ctx); 45 | for (guint i = 0; i < repos->len; ++i) 46 | { 47 | DnfRepo * repo = g_ptr_array_index (repos, i); 48 | dnf_repo_set_enabled (repo, DNF_REPO_ENABLED_NONE); 49 | } 50 | } 51 | 52 | static gboolean 53 | dnf_command_remove_run (DnfCommand *cmd, 54 | int argc, 55 | char *argv[], 56 | GOptionContext *opt_ctx, 57 | DnfContext *ctx, 58 | GError **error) 59 | { 60 | g_auto(GStrv) pkgs = NULL; 61 | const GOptionEntry opts[] = { 62 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 63 | { NULL } 64 | }; 65 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 66 | 67 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 68 | return FALSE; 69 | 70 | if (pkgs == NULL) 71 | { 72 | g_set_error_literal (error, 73 | G_IO_ERROR, 74 | G_IO_ERROR_FAILED, 75 | "Packages are not specified"); 76 | return FALSE; 77 | } 78 | 79 | disable_available_repos (ctx); 80 | 81 | /* Remove each package */ 82 | for (GStrv pkg = pkgs; *pkg != NULL; pkg++) 83 | { 84 | if (!dnf_context_remove (ctx, *pkg, error)) 85 | return FALSE; 86 | } 87 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), DNF_ERASE, error)) 88 | return FALSE; 89 | dnf_utils_print_transaction (ctx); 90 | if (!dnf_utils_userconfirm ()) 91 | return FALSE; 92 | if (!dnf_context_run (ctx, NULL, error)) 93 | return FALSE; 94 | g_print ("Complete.\n"); 95 | 96 | return TRUE; 97 | } 98 | 99 | static void 100 | dnf_command_remove_class_init (DnfCommandRemoveClass *klass) 101 | { 102 | } 103 | 104 | static void 105 | dnf_command_remove_iface_init (DnfCommandInterface *iface) 106 | { 107 | iface->run = dnf_command_remove_run; 108 | } 109 | 110 | static void 111 | dnf_command_remove_class_finalize (DnfCommandRemoveClass *klass) 112 | { 113 | } 114 | 115 | G_MODULE_EXPORT void 116 | dnf_command_remove_register_types (PeasObjectModule *module) 117 | { 118 | dnf_command_remove_register_type (G_TYPE_MODULE (module)); 119 | 120 | peas_object_module_register_extension_type (module, 121 | DNF_TYPE_COMMAND, 122 | DNF_TYPE_COMMAND_REMOVE); 123 | } 124 | -------------------------------------------------------------------------------- /dnf/plugins/install/dnf-command-install.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-install.c 2 | * 3 | * Copyright © 2010-2015 Richard Hughes 4 | * Copyright © 2016 Colin Walters 5 | * Copyright © 2016-2017 Igor Gnatenko 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include "dnf-command-install.h" 22 | #include "dnf-utils.h" 23 | 24 | struct _DnfCommandInstall 25 | { 26 | PeasExtensionBase parent_instance; 27 | }; 28 | 29 | static void dnf_command_install_iface_init (DnfCommandInterface *iface); 30 | 31 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandInstall, 32 | dnf_command_install, 33 | PEAS_TYPE_EXTENSION_BASE, 34 | 0, 35 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 36 | dnf_command_install_iface_init)) 37 | 38 | static void 39 | dnf_command_install_init (DnfCommandInstall *self) 40 | { 41 | } 42 | 43 | static gboolean 44 | dnf_command_install_run (DnfCommand *cmd, 45 | int argc, 46 | char *argv[], 47 | GOptionContext *opt_ctx, 48 | DnfContext *ctx, 49 | GError **error) 50 | { 51 | g_auto(GStrv) pkgs = NULL; 52 | const GOptionEntry opts[] = { 53 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 54 | { NULL } 55 | }; 56 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 57 | 58 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 59 | return FALSE; 60 | 61 | if (pkgs == NULL) 62 | { 63 | g_set_error_literal (error, 64 | G_IO_ERROR, 65 | G_IO_ERROR_FAILED, 66 | "Packages are not specified"); 67 | return FALSE; 68 | } 69 | 70 | /* Install each package */ 71 | for (GStrv pkg = pkgs; *pkg != NULL; pkg++) 72 | { 73 | if (!dnf_context_install (ctx, *pkg, error)) 74 | return FALSE; 75 | } 76 | DnfGoalActions flags = DNF_INSTALL; 77 | if (dnf_context_get_best()) 78 | { 79 | flags |= DNF_FORCE_BEST; 80 | } 81 | if (!dnf_context_get_install_weak_deps ()) 82 | flags |= DNF_IGNORE_WEAK_DEPS; 83 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), flags, error)) 84 | return FALSE; 85 | if (!dnf_utils_print_transaction (ctx)) 86 | return TRUE; 87 | if (!dnf_utils_userconfirm ()) 88 | return FALSE; 89 | if (!dnf_context_run (ctx, NULL, error)) 90 | return FALSE; 91 | g_print ("Complete.\n"); 92 | 93 | return TRUE; 94 | } 95 | 96 | static void 97 | dnf_command_install_class_init (DnfCommandInstallClass *klass) 98 | { 99 | } 100 | 101 | static void 102 | dnf_command_install_iface_init (DnfCommandInterface *iface) 103 | { 104 | iface->run = dnf_command_install_run; 105 | } 106 | 107 | static void 108 | dnf_command_install_class_finalize (DnfCommandInstallClass *klass) 109 | { 110 | } 111 | 112 | G_MODULE_EXPORT void 113 | dnf_command_install_register_types (PeasObjectModule *module) 114 | { 115 | dnf_command_install_register_type (G_TYPE_MODULE (module)); 116 | 117 | peas_object_module_register_extension_type (module, 118 | DNF_TYPE_COMMAND, 119 | DNF_TYPE_COMMAND_INSTALL); 120 | } 121 | -------------------------------------------------------------------------------- /dnf/plugins/module_disable/dnf-command-module_disable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "dnf-command-module_disable.h" 22 | #include "dnf-utils.h" 23 | 24 | struct _DnfCommandModuleDisable 25 | { 26 | PeasExtensionBase parent_instance; 27 | }; 28 | 29 | static void dnf_command_module_disable_iface_init (DnfCommandInterface *iface); 30 | 31 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandModuleDisable, 32 | dnf_command_module_disable, 33 | PEAS_TYPE_EXTENSION_BASE, 34 | 0, 35 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 36 | dnf_command_module_disable_iface_init)) 37 | 38 | static void 39 | dnf_command_module_disable_init (DnfCommandModuleDisable *self) 40 | { 41 | } 42 | 43 | static gboolean 44 | dnf_command_module_disable_run (DnfCommand *cmd, 45 | int argc, 46 | char *argv[], 47 | GOptionContext *opt_ctx, 48 | DnfContext *ctx, 49 | GError **error) 50 | { 51 | g_auto(GStrv) pkgs = NULL; 52 | const GOptionEntry opts[] = { 53 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 54 | { NULL } 55 | }; 56 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 57 | 58 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 59 | return FALSE; 60 | 61 | if (pkgs == NULL) 62 | { 63 | g_set_error_literal (error, 64 | G_IO_ERROR, 65 | G_IO_ERROR_FAILED, 66 | "Modules are not specified"); 67 | return FALSE; 68 | } 69 | 70 | if (!dnf_context_module_disable (ctx, (const char **)pkgs, error)) 71 | { 72 | return FALSE; 73 | } 74 | 75 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), DNF_NONE, error)) 76 | { 77 | if (g_error_matches (*error, DNF_ERROR, DNF_ERROR_NO_PACKAGES_TO_UPDATE)) 78 | { 79 | g_clear_error (error); 80 | } else { 81 | return FALSE; 82 | } 83 | } 84 | if (!dnf_utils_print_transaction (ctx)) 85 | { 86 | return TRUE; 87 | } 88 | if (!dnf_utils_userconfirm ()) 89 | { 90 | return FALSE; 91 | } 92 | if (!dnf_context_run (ctx, NULL, error)) 93 | { 94 | return FALSE; 95 | } 96 | return TRUE; 97 | } 98 | 99 | static void 100 | dnf_command_module_disable_class_init (DnfCommandModuleDisableClass *klass) 101 | { 102 | } 103 | 104 | static void 105 | dnf_command_module_disable_iface_init (DnfCommandInterface *iface) 106 | { 107 | iface->run = dnf_command_module_disable_run; 108 | } 109 | 110 | static void 111 | dnf_command_module_disable_class_finalize (DnfCommandModuleDisableClass *klass) 112 | { 113 | } 114 | 115 | G_MODULE_EXPORT void 116 | dnf_command_module_disable_register_types (PeasObjectModule *module) 117 | { 118 | dnf_command_module_disable_register_type (G_TYPE_MODULE (module)); 119 | 120 | peas_object_module_register_extension_type (module, 121 | DNF_TYPE_COMMAND, 122 | DNF_TYPE_COMMAND_MODULE_DISABLE); 123 | } 124 | -------------------------------------------------------------------------------- /dnf/plugins/module_reset/dnf-command-module_reset.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "dnf-command-module_reset.h" 22 | #include "dnf-utils.h" 23 | 24 | struct _DnfCommandModuleReset 25 | { 26 | PeasExtensionBase parent_instance; 27 | }; 28 | 29 | static void dnf_command_module_reset_iface_init (DnfCommandInterface *iface); 30 | 31 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandModuleReset, 32 | dnf_command_module_reset, 33 | PEAS_TYPE_EXTENSION_BASE, 34 | 0, 35 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 36 | dnf_command_module_reset_iface_init)) 37 | 38 | static void 39 | dnf_command_module_reset_init (DnfCommandModuleReset *self) 40 | { 41 | } 42 | 43 | static gboolean 44 | dnf_command_module_reset_run (DnfCommand *cmd, 45 | int argc, 46 | char *argv[], 47 | GOptionContext *opt_ctx, 48 | DnfContext *ctx, 49 | GError **error) 50 | { 51 | g_auto(GStrv) pkgs = NULL; 52 | const GOptionEntry opts[] = { 53 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 54 | { NULL } 55 | }; 56 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 57 | 58 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 59 | return FALSE; 60 | 61 | if (pkgs == NULL) 62 | { 63 | g_set_error_literal (error, 64 | G_IO_ERROR, 65 | G_IO_ERROR_FAILED, 66 | "Modules are not specified"); 67 | return FALSE; 68 | } 69 | 70 | if (!dnf_context_module_reset (ctx, (const char **)pkgs, error)) 71 | { 72 | return FALSE; 73 | } 74 | if (!dnf_context_module_switched_check (ctx, error)) 75 | { 76 | return FALSE; 77 | } 78 | 79 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), DNF_NONE, error)) 80 | { 81 | if (g_error_matches (*error, DNF_ERROR, DNF_ERROR_NO_PACKAGES_TO_UPDATE)) 82 | { 83 | g_clear_error (error); 84 | } else { 85 | return FALSE; 86 | } 87 | } 88 | if (!dnf_utils_print_transaction (ctx)) 89 | { 90 | return TRUE; 91 | } 92 | if (!dnf_utils_userconfirm ()) 93 | { 94 | return FALSE; 95 | } 96 | if (!dnf_context_run (ctx, NULL, error)) 97 | { 98 | return FALSE; 99 | } 100 | return TRUE; 101 | } 102 | 103 | static void 104 | dnf_command_module_reset_class_init (DnfCommandModuleResetClass *klass) 105 | { 106 | } 107 | 108 | static void 109 | dnf_command_module_reset_iface_init (DnfCommandInterface *iface) 110 | { 111 | iface->run = dnf_command_module_reset_run; 112 | } 113 | 114 | static void 115 | dnf_command_module_reset_class_finalize (DnfCommandModuleResetClass *klass) 116 | { 117 | } 118 | 119 | G_MODULE_EXPORT void 120 | dnf_command_module_reset_register_types (PeasObjectModule *module) 121 | { 122 | dnf_command_module_reset_register_type (G_TYPE_MODULE (module)); 123 | 124 | peas_object_module_register_extension_type (module, 125 | DNF_TYPE_COMMAND, 126 | DNF_TYPE_COMMAND_MODULE_RESET); 127 | } 128 | -------------------------------------------------------------------------------- /dnf/plugins/module_enable/dnf-command-module_enable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "dnf-command-module_enable.h" 22 | #include "dnf-utils.h" 23 | 24 | struct _DnfCommandModuleEnable 25 | { 26 | PeasExtensionBase parent_instance; 27 | }; 28 | 29 | static void dnf_command_module_enable_iface_init (DnfCommandInterface *iface); 30 | 31 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandModuleEnable, 32 | dnf_command_module_enable, 33 | PEAS_TYPE_EXTENSION_BASE, 34 | 0, 35 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 36 | dnf_command_module_enable_iface_init)) 37 | 38 | static void 39 | dnf_command_module_enable_init (DnfCommandModuleEnable *self) 40 | { 41 | } 42 | 43 | static gboolean 44 | dnf_command_module_enable_run (DnfCommand *cmd, 45 | int argc, 46 | char *argv[], 47 | GOptionContext *opt_ctx, 48 | DnfContext *ctx, 49 | GError **error) 50 | { 51 | g_auto(GStrv) pkgs = NULL; 52 | const GOptionEntry opts[] = { 53 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 54 | { NULL } 55 | }; 56 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 57 | 58 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 59 | return FALSE; 60 | 61 | if (pkgs == NULL) 62 | { 63 | g_set_error_literal (error, 64 | G_IO_ERROR, 65 | G_IO_ERROR_FAILED, 66 | "Modules are not specified"); 67 | return FALSE; 68 | } 69 | 70 | if (!dnf_context_module_enable (ctx, (const char **)pkgs, error)) 71 | { 72 | return FALSE; 73 | } 74 | if (!dnf_context_module_switched_check (ctx, error)) 75 | { 76 | return FALSE; 77 | } 78 | 79 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), DNF_NONE, error)) 80 | { 81 | if (g_error_matches (*error, DNF_ERROR, DNF_ERROR_NO_PACKAGES_TO_UPDATE)) 82 | { 83 | g_clear_error (error); 84 | } else { 85 | return FALSE; 86 | } 87 | } 88 | if (!dnf_utils_print_transaction (ctx)) 89 | { 90 | return TRUE; 91 | } 92 | if (!dnf_utils_userconfirm ()) 93 | { 94 | return FALSE; 95 | } 96 | if (!dnf_context_run (ctx, NULL, error)) 97 | { 98 | return FALSE; 99 | } 100 | return TRUE; 101 | } 102 | 103 | static void 104 | dnf_command_module_enable_class_init (DnfCommandModuleEnableClass *klass) 105 | { 106 | } 107 | 108 | static void 109 | dnf_command_module_enable_iface_init (DnfCommandInterface *iface) 110 | { 111 | iface->run = dnf_command_module_enable_run; 112 | } 113 | 114 | static void 115 | dnf_command_module_enable_class_finalize (DnfCommandModuleEnableClass *klass) 116 | { 117 | } 118 | 119 | G_MODULE_EXPORT void 120 | dnf_command_module_enable_register_types (PeasObjectModule *module) 121 | { 122 | dnf_command_module_enable_register_type (G_TYPE_MODULE (module)); 123 | 124 | peas_object_module_register_extension_type (module, 125 | DNF_TYPE_COMMAND, 126 | DNF_TYPE_COMMAND_MODULE_ENABLE); 127 | } 128 | -------------------------------------------------------------------------------- /dnf/plugins/clean/dnf-command-clean.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-clean.c 2 | * 3 | * Copyright © 2017 Jaroslav Rohel 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command-clean.h" 20 | 21 | struct _DnfCommandClean 22 | { 23 | PeasExtensionBase parent_instance; 24 | }; 25 | 26 | static void dnf_command_clean_iface_init (DnfCommandInterface *iface); 27 | 28 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandClean, 29 | dnf_command_clean, 30 | PEAS_TYPE_EXTENSION_BASE, 31 | 0, 32 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 33 | dnf_command_clean_iface_init)) 34 | 35 | static void 36 | dnf_command_clean_init (DnfCommandClean *self) 37 | { 38 | } 39 | 40 | static gboolean 41 | dnf_command_clean_run (DnfCommand *cmd, 42 | int argc, 43 | char *argv[], 44 | GOptionContext *opt_ctx, 45 | DnfContext *ctx, 46 | GError **error) 47 | { 48 | g_auto(GStrv) types = NULL; 49 | const GOptionEntry opts[] = { 50 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &types, NULL, NULL }, 51 | { NULL } 52 | }; 53 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 54 | 55 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 56 | return FALSE; 57 | 58 | if (types == NULL) 59 | { 60 | g_set_error_literal (error, 61 | G_IO_ERROR, 62 | G_IO_ERROR_FAILED, 63 | "Clean requires argument: all"); 64 | return FALSE; 65 | } 66 | 67 | if (g_strcmp0 (types[0], "all") != 0) 68 | { 69 | g_set_error (error, 70 | G_IO_ERROR, 71 | G_IO_ERROR_FAILED, 72 | "Invalid clean argument: '%s'", *types); 73 | return FALSE; 74 | } 75 | 76 | if (types[1] != NULL) 77 | { 78 | g_set_error_literal (error, 79 | G_IO_ERROR, 80 | G_IO_ERROR_FAILED, 81 | "Too many arguments. Clean accepts only one argument."); 82 | return FALSE; 83 | } 84 | 85 | /* lock cache */ 86 | g_autoptr(DnfLock) lock = dnf_lock_new (); 87 | dnf_lock_set_lock_dir (lock, dnf_context_get_lock_dir (ctx)); 88 | guint lock_id = dnf_lock_take (lock, 89 | DNF_LOCK_TYPE_METADATA, 90 | DNF_LOCK_MODE_PROCESS, 91 | error); 92 | if (lock_id == 0) 93 | return FALSE; 94 | 95 | /* Clean cached data */ 96 | const gchar *cachedir = dnf_context_get_cache_dir (ctx); 97 | if (!dnf_remove_recursive (cachedir, error)) 98 | return FALSE; 99 | const gchar *solvdir = dnf_context_get_solv_dir (ctx); 100 | if (!dnf_remove_recursive (solvdir, error)) 101 | return FALSE; 102 | 103 | if (!dnf_lock_release (lock, lock_id, error)) 104 | return FALSE; 105 | 106 | g_print ("Complete.\n"); 107 | 108 | return TRUE; 109 | } 110 | 111 | static void 112 | dnf_command_clean_class_init (DnfCommandCleanClass *klass) 113 | { 114 | } 115 | 116 | static void 117 | dnf_command_clean_iface_init (DnfCommandInterface *iface) 118 | { 119 | iface->run = dnf_command_clean_run; 120 | } 121 | 122 | static void 123 | dnf_command_clean_class_finalize (DnfCommandCleanClass *klass) 124 | { 125 | } 126 | 127 | G_MODULE_EXPORT void 128 | dnf_command_clean_register_types (PeasObjectModule *module) 129 | { 130 | dnf_command_clean_register_type (G_TYPE_MODULE (module)); 131 | 132 | peas_object_module_register_extension_type (module, 133 | DNF_TYPE_COMMAND, 134 | DNF_TYPE_COMMAND_CLEAN); 135 | } 136 | -------------------------------------------------------------------------------- /dnf/meson.build: -------------------------------------------------------------------------------- 1 | microdnf_srcs = [ 2 | 'dnf-main.c', 3 | 'dnf-command.c', 4 | 'dnf-utils.c', 5 | 6 | # install 7 | gnome.compile_resources( 8 | 'dnf-install', 9 | 'plugins/install/dnf-command-install.gresource.xml', 10 | c_name : 'dnf_command_install', 11 | source_dir : 'plugins/install', 12 | ), 13 | 'plugins/install/dnf-command-install.c', 14 | 15 | # reinstall 16 | gnome.compile_resources( 17 | 'dnf-reinstall', 18 | 'plugins/reinstall/dnf-command-reinstall.gresource.xml', 19 | c_name : 'dnf_command_reinstall', 20 | source_dir : 'plugins/reinstall', 21 | ), 22 | 'plugins/reinstall/dnf-command-reinstall.c', 23 | 24 | # remove 25 | gnome.compile_resources( 26 | 'dnf-remove', 27 | 'plugins/remove/dnf-command-remove.gresource.xml', 28 | c_name : 'dnf_command_remove', 29 | source_dir : 'plugins/remove', 30 | ), 31 | 'plugins/remove/dnf-command-remove.c', 32 | 33 | # upgrade 34 | gnome.compile_resources( 35 | 'dnf-upgrade', 36 | 'plugins/upgrade/dnf-command-upgrade.gresource.xml', 37 | c_name : 'dnf_command_upgrade', 38 | source_dir : 'plugins/upgrade', 39 | ), 40 | 'plugins/upgrade/dnf-command-upgrade.c', 41 | 42 | # swap 43 | gnome.compile_resources( 44 | 'dnf-swap', 45 | 'plugins/swap/dnf-command-swap.gresource.xml', 46 | c_name : 'dnf_command_swap', 47 | source_dir : 'plugins/swap', 48 | ), 49 | 'plugins/swap/dnf-command-swap.c', 50 | 51 | # distro-sync 52 | gnome.compile_resources( 53 | 'dnf-distrosync', 54 | 'plugins/distrosync/dnf-command-distrosync.gresource.xml', 55 | c_name : 'dnf_command_distrosync', 56 | source_dir : 'plugins/distrosync', 57 | ), 58 | 'plugins/distrosync/dnf-command-distrosync.c', 59 | 60 | # repolist 61 | gnome.compile_resources( 62 | 'dnf-repolist', 63 | 'plugins/repolist/dnf-command-repolist.gresource.xml', 64 | c_name : 'dnf_command_repolist', 65 | source_dir : 'plugins/repolist', 66 | ), 67 | 'plugins/repolist/dnf-command-repolist.c', 68 | 69 | # repoquery 70 | gnome.compile_resources( 71 | 'dnf-repoquery', 72 | 'plugins/repoquery/dnf-command-repoquery.gresource.xml', 73 | c_name : 'dnf_command_repoquery', 74 | source_dir : 'plugins/repoquery', 75 | ), 76 | 'plugins/repoquery/dnf-command-repoquery.c', 77 | 78 | # leaves 79 | gnome.compile_resources( 80 | 'dnf-leaves', 81 | 'plugins/leaves/dnf-command-leaves.gresource.xml', 82 | c_name : 'dnf_command_leaves', 83 | source_dir : 'plugins/leaves', 84 | ), 85 | 'plugins/leaves/dnf-command-leaves.c', 86 | 87 | # clean 88 | gnome.compile_resources( 89 | 'dnf-clean', 90 | 'plugins/clean/dnf-command-clean.gresource.xml', 91 | c_name : 'dnf_command_clean', 92 | source_dir : 'plugins/clean', 93 | ), 94 | 'plugins/clean/dnf-command-clean.c', 95 | 96 | # download 97 | gnome.compile_resources( 98 | 'dnf-download', 99 | 'plugins/download/dnf-command-download.gresource.xml', 100 | c_name : 'dnf_command_download', 101 | source_dir : 'plugins/download', 102 | ), 103 | 'plugins/download/dnf-command-download.c', 104 | 105 | # makecache 106 | gnome.compile_resources( 107 | 'dnf-makecache', 108 | 'plugins/makecache/dnf-command-makecache.gresource.xml', 109 | c_name : 'dnf_command_makecache', 110 | source_dir : 'plugins/makecache', 111 | ), 112 | 'plugins/makecache/dnf-command-makecache.c', 113 | 114 | # module enable 115 | gnome.compile_resources( 116 | 'dnf-module_enable', 117 | 'plugins/module_enable/dnf-command-module_enable.gresource.xml', 118 | c_name : 'dnf_command_module_enable', 119 | source_dir : 'plugins/module_enable', 120 | ), 121 | 'plugins/module_enable/dnf-command-module_enable.c', 122 | 123 | # module disable 124 | gnome.compile_resources( 125 | 'dnf-module_disable', 126 | 'plugins/module_disable/dnf-command-module_disable.gresource.xml', 127 | c_name : 'dnf_command_module_disable', 128 | source_dir : 'plugins/module_disable', 129 | ), 130 | 'plugins/module_disable/dnf-command-module_disable.c', 131 | 132 | # module reset 133 | gnome.compile_resources( 134 | 'dnf-module_reset', 135 | 'plugins/module_reset/dnf-command-module_reset.gresource.xml', 136 | c_name : 'dnf_command_module_reset', 137 | source_dir : 'plugins/module_reset', 138 | ), 139 | 'plugins/module_reset/dnf-command-module_reset.c', 140 | ] 141 | 142 | microdnf = executable( 143 | 'microdnf', 144 | sources : microdnf_srcs, 145 | dependencies : [ 146 | glib, 147 | gobject, 148 | libpeas, 149 | libdnf, 150 | scols, 151 | ], 152 | c_args : [ 153 | '-DBUILDDIR="@0@"'.format(meson.current_build_dir()), 154 | '-DSRCDIR="@0@"'.format(meson.current_source_dir()), 155 | ], 156 | install : true 157 | ) 158 | -------------------------------------------------------------------------------- /dnf/plugins/swap/dnf-command-swap.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-swap.c 2 | * 3 | * Copyright (C) 2022 Red Hat, Inc. 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command-swap.h" 20 | #include "dnf-utils.h" 21 | 22 | struct _DnfCommandSwap 23 | { 24 | PeasExtensionBase parent_instance; 25 | }; 26 | 27 | static void dnf_command_swap_iface_init (DnfCommandInterface *iface); 28 | 29 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandSwap, 30 | dnf_command_swap, 31 | PEAS_TYPE_EXTENSION_BASE, 32 | 0, 33 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 34 | dnf_command_swap_iface_init)) 35 | 36 | static void 37 | dnf_command_swap_init (DnfCommandSwap *self) 38 | { 39 | } 40 | 41 | static gboolean 42 | dnf_command_swap_run (DnfCommand *cmd, 43 | int argc, 44 | char *argv[], 45 | GOptionContext *opt_ctx, 46 | DnfContext *ctx, 47 | GError **error) 48 | { 49 | g_auto(GStrv) pkgs = NULL; 50 | const GOptionEntry opts[] = { 51 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 52 | { NULL } 53 | }; 54 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 55 | 56 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 57 | return FALSE; 58 | 59 | if (pkgs == NULL || pkgs[0] == NULL) 60 | { 61 | g_set_error_literal (error, 62 | G_IO_ERROR, 63 | G_IO_ERROR_FAILED, 64 | "Missing arguments. " 65 | "The swap command requires 2 arguments: PACKAGE_TO_REMOVE and PACKAGE_TO_INSTALL."); 66 | return FALSE; 67 | } 68 | 69 | if (pkgs[1] == NULL) 70 | { 71 | g_set_error_literal (error, 72 | G_IO_ERROR, 73 | G_IO_ERROR_FAILED, 74 | "Missing argument. " 75 | "The swap command requires 2 arguments: PACKAGE_TO_REMOVE and PACKAGE_TO_INSTALL."); 76 | return FALSE; 77 | } 78 | 79 | if (pkgs[2] != NULL) 80 | { 81 | g_set_error_literal (error, 82 | G_IO_ERROR, 83 | G_IO_ERROR_FAILED, 84 | "Too many arguments. " 85 | "The swap command requires 2 arguments: PACKAGE_TO_REMOVE and PACKAGE_TO_INSTALL."); 86 | return FALSE; 87 | } 88 | 89 | /* Install new package */ 90 | if (!dnf_context_install (ctx, pkgs[1], error)) 91 | return FALSE; 92 | /* Remove package */ 93 | if (!dnf_context_remove (ctx, pkgs[0], error)) 94 | return FALSE; 95 | DnfGoalActions flags = DNF_INSTALL | DNF_ERASE; 96 | if (dnf_context_get_best()) 97 | flags |= DNF_FORCE_BEST; 98 | if (!dnf_context_get_install_weak_deps ()) 99 | flags |= DNF_IGNORE_WEAK_DEPS; 100 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), flags, error)) 101 | return FALSE; 102 | if (!dnf_utils_print_transaction (ctx)) 103 | return TRUE; 104 | if (!dnf_utils_userconfirm ()) 105 | return FALSE; 106 | if (!dnf_context_run (ctx, NULL, error)) 107 | return FALSE; 108 | g_print ("Complete.\n"); 109 | 110 | return TRUE; 111 | } 112 | 113 | static void 114 | dnf_command_swap_class_init (DnfCommandSwapClass *klass) 115 | { 116 | } 117 | 118 | static void 119 | dnf_command_swap_iface_init (DnfCommandInterface *iface) 120 | { 121 | iface->run = dnf_command_swap_run; 122 | } 123 | 124 | static void 125 | dnf_command_swap_class_finalize (DnfCommandSwapClass *klass) 126 | { 127 | } 128 | 129 | G_MODULE_EXPORT void 130 | dnf_command_swap_register_types (PeasObjectModule *module) 131 | { 132 | dnf_command_swap_register_type (G_TYPE_MODULE (module)); 133 | 134 | peas_object_module_register_extension_type (module, 135 | DNF_TYPE_COMMAND, 136 | DNF_TYPE_COMMAND_SWAP); 137 | } 138 | -------------------------------------------------------------------------------- /dnf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (DNF_SRCS dnf-command.c dnf-utils.c) 2 | 3 | glib_compile_resources (DNF_COMMAND_INSTALL plugins/install/dnf-command-install.gresource.xml 4 | C_PREFIX dnf_command_install 5 | INTERNAL) 6 | list (APPEND DNF_COMMAND_INSTALL "plugins/install/dnf-command-install.c") 7 | 8 | glib_compile_resources (DNF_COMMAND_REINSTALL plugins/reinstall/dnf-command-reinstall.gresource.xml 9 | C_PREFIX dnf_command_reinstall 10 | INTERNAL) 11 | list (APPEND DNF_COMMAND_REINSTALL "plugins/reinstall/dnf-command-reinstall.c") 12 | 13 | glib_compile_resources (DNF_COMMAND_REMOVE plugins/remove/dnf-command-remove.gresource.xml 14 | C_PREFIX dnf_command_remove 15 | INTERNAL) 16 | list (APPEND DNF_COMMAND_REMOVE "plugins/remove/dnf-command-remove.c") 17 | 18 | glib_compile_resources (DNF_COMMAND_UPGRADE plugins/upgrade/dnf-command-upgrade.gresource.xml 19 | C_PREFIX dnf_command_upgrade 20 | INTERNAL) 21 | list (APPEND DNF_COMMAND_UPGRADE "plugins/upgrade/dnf-command-upgrade.c") 22 | 23 | glib_compile_resources (DNF_COMMAND_SWAP plugins/swap/dnf-command-swap.gresource.xml 24 | C_PREFIX dnf_command_swap 25 | INTERNAL) 26 | list (APPEND DNF_COMMAND_SWAP "plugins/swap/dnf-command-swap.c") 27 | 28 | glib_compile_resources (DNF_COMMAND_DISTROSYNC plugins/distrosync/dnf-command-distrosync.gresource.xml 29 | C_PREFIX dnf_command_distrosync 30 | INTERNAL) 31 | list (APPEND DNF_COMMAND_DISTROSYNC "plugins/distrosync/dnf-command-distrosync.c") 32 | 33 | glib_compile_resources (DNF_COMMAND_REPOLIST plugins/repolist/dnf-command-repolist.gresource.xml 34 | C_PREFIX dnf_command_repolist 35 | INTERNAL) 36 | list (APPEND DNF_COMMAND_REPOLIST "plugins/repolist/dnf-command-repolist.c") 37 | 38 | glib_compile_resources (DNF_COMMAND_REPOQUERY plugins/repoquery/dnf-command-repoquery.gresource.xml 39 | C_PREFIX dnf_command_repoquery 40 | INTERNAL) 41 | list (APPEND DNF_COMMAND_REPOQUERY "plugins/repoquery/dnf-command-repoquery.c") 42 | 43 | glib_compile_resources (DNF_COMMAND_LEAVES plugins/leaves/dnf-command-leaves.gresource.xml 44 | C_PREFIX dnf_command_leaves 45 | INTERNAL) 46 | list (APPEND DNF_COMMAND_LEAVES "plugins/leaves/dnf-command-leaves.c") 47 | 48 | glib_compile_resources (DNF_COMMAND_CLEAN plugins/clean/dnf-command-clean.gresource.xml 49 | C_PREFIX dnf_command_clean 50 | INTERNAL) 51 | list (APPEND DNF_COMMAND_CLEAN "plugins/clean/dnf-command-clean.c") 52 | 53 | glib_compile_resources (DNF_COMMAND_DOWNLOAD plugins/download/dnf-command-download.gresource.xml 54 | C_PREFIX dnf_command_download 55 | INTERNAL) 56 | list (APPEND DNF_COMMAND_DOWNLOAD "plugins/download/dnf-command-download.c") 57 | 58 | glib_compile_resources (DNF_COMMAND_MAKECACHE plugins/makecache/dnf-command-makecache.gresource.xml 59 | C_PREFIX dnf_command_makecache 60 | INTERNAL) 61 | list (APPEND DNF_COMMAND_MAKECACHE "plugins/makecache/dnf-command-makecache.c") 62 | 63 | glib_compile_resources (DNF_COMMAND_MODULE_ENABLE plugins/module_enable/dnf-command-module_enable.gresource.xml 64 | C_PREFIX dnf_command_module_enable 65 | INTERNAL) 66 | list (APPEND DNF_COMMAND_MODULE_ENABLE "plugins/module_enable/dnf-command-module_enable.c") 67 | 68 | glib_compile_resources (DNF_COMMAND_MODULE_DISABLE plugins/module_disable/dnf-command-module_disable.gresource.xml 69 | C_PREFIX dnf_command_module_disable 70 | INTERNAL) 71 | list (APPEND DNF_COMMAND_MODULE_DISABLE "plugins/module_disable/dnf-command-module_disable.c") 72 | 73 | glib_compile_resources (DNF_COMMAND_MODULE_RESET plugins/module_reset/dnf-command-module_reset.gresource.xml 74 | C_PREFIX dnf_command_module_reset 75 | INTERNAL) 76 | list (APPEND DNF_COMMAND_MODULE_RESET "plugins/module_reset/dnf-command-module_reset.c") 77 | 78 | 79 | include_directories (${CMAKE_CURRENT_SOURCE_DIR}) 80 | add_executable (microdnf dnf-main.c ${DNF_SRCS} 81 | ${DNF_COMMAND_INSTALL} 82 | ${DNF_COMMAND_REINSTALL} 83 | ${DNF_COMMAND_REMOVE} 84 | ${DNF_COMMAND_UPGRADE} 85 | ${DNF_COMMAND_SWAP} 86 | ${DNF_COMMAND_DISTROSYNC} 87 | ${DNF_COMMAND_REPOLIST} 88 | ${DNF_COMMAND_REPOQUERY} 89 | ${DNF_COMMAND_LEAVES} 90 | ${DNF_COMMAND_CLEAN} 91 | ${DNF_COMMAND_DOWNLOAD} 92 | ${DNF_COMMAND_MAKECACHE} 93 | ${DNF_COMMAND_MODULE_ENABLE} 94 | ${DNF_COMMAND_MODULE_DISABLE} 95 | ${DNF_COMMAND_MODULE_RESET}) 96 | 97 | target_link_libraries (microdnf 98 | ${GLIB_LIBRARIES} 99 | ${GOBJECT_LIBRARIES} 100 | ${PEAS_LIBRARIES} 101 | ${LIBDNF_LIBRARIES} 102 | ${SCOLS_LIBRARIES}) 103 | target_compile_definitions (microdnf 104 | PRIVATE -DBUILDDIR="${CMAKE_CURRENT_BINARY_DIR}" 105 | PRIVATE -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}") 106 | 107 | add_subdirectory (plugins) 108 | 109 | install (TARGETS microdnf 110 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 111 | -------------------------------------------------------------------------------- /dnf/plugins/repolist/dnf-command-repolist.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "dnf-command-repolist.h" 22 | 23 | #include 24 | #include 25 | 26 | struct _DnfCommandRepolist 27 | { 28 | PeasExtensionBase parent_instance; 29 | }; 30 | 31 | static void dnf_command_repolist_iface_init (DnfCommandInterface *iface); 32 | 33 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandRepolist, 34 | dnf_command_repolist, 35 | PEAS_TYPE_EXTENSION_BASE, 36 | 0, 37 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 38 | dnf_command_repolist_iface_init)) 39 | 40 | static void 41 | dnf_command_repolist_init (DnfCommandRepolist *self) 42 | { 43 | } 44 | 45 | // repository list table columns 46 | enum { COL_REPO_ID, COL_REPO_NAME, COL_REPO_STATUS }; 47 | 48 | static struct libscols_table * 49 | create_repolist_table (gboolean with_status) 50 | { 51 | struct libscols_table *table = scols_new_table (); 52 | if (isatty (1)) 53 | { 54 | scols_table_enable_colors (table, 1); 55 | scols_table_enable_maxout (table, 1); 56 | } 57 | struct libscols_column *cl = scols_table_new_column (table, "repo id", 0.4, 0); 58 | scols_column_set_cmpfunc(cl, scols_cmpstr_cells, NULL); 59 | scols_table_new_column (table, "repo name", 0.5, SCOLS_FL_TRUNC); 60 | if (with_status) 61 | scols_table_new_column (table, "status", 0.1, SCOLS_FL_RIGHT); 62 | return table; 63 | } 64 | 65 | static void 66 | add_line_into_table (struct libscols_table *table, 67 | gboolean with_status, 68 | const char *id, 69 | const char *descr, 70 | gboolean enabled) 71 | { 72 | struct libscols_line *ln = scols_table_new_line (table, NULL); 73 | scols_line_set_data (ln, COL_REPO_ID, id); 74 | scols_line_set_data (ln, COL_REPO_NAME, descr); 75 | if (with_status) 76 | { 77 | scols_line_set_data (ln, COL_REPO_STATUS, enabled ? "enabled" : "disabled"); 78 | struct libscols_cell * cl = scols_line_get_cell (ln, COL_REPO_STATUS); 79 | scols_cell_set_color (cl, enabled ? "green" : "red"); 80 | } 81 | } 82 | 83 | static gboolean 84 | dnf_command_repolist_run (DnfCommand *cmd, 85 | int argc, 86 | char *argv[], 87 | GOptionContext *opt_ctx, 88 | DnfContext *ctx, 89 | GError **error) 90 | { 91 | gboolean opt_all = FALSE; 92 | gboolean opt_enabled = FALSE; 93 | gboolean opt_disabled = FALSE; 94 | g_auto(GStrv) opt_repos = NULL; 95 | const GOptionEntry opts[] = { 96 | { "all", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_all, "show all repos", NULL }, 97 | { "disabled", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_disabled, "show disabled repos", NULL }, 98 | { "enabled", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_enabled, "show enabled repos (default)", NULL }, 99 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_repos, NULL, NULL }, 100 | { NULL } 101 | }; 102 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 103 | 104 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 105 | return FALSE; 106 | 107 | if (opt_repos && opt_repos[0]) 108 | { 109 | g_set_error (error, 110 | G_OPTION_ERROR, 111 | G_OPTION_ERROR_UNKNOWN_OPTION, 112 | "Unknown argument %s", opt_repos[0]); 113 | return FALSE; 114 | } 115 | 116 | if (!opt_disabled) 117 | opt_enabled = TRUE; 118 | 119 | if (opt_enabled && opt_disabled) 120 | opt_all = TRUE; 121 | 122 | struct libscols_table *table = create_repolist_table (opt_all); 123 | 124 | GPtrArray *repos = dnf_context_get_repos (ctx); 125 | for (guint i = 0; i < repos->len; ++i) 126 | { 127 | DnfRepo * repo = g_ptr_array_index (repos, i); 128 | gboolean enabled = dnf_repo_get_enabled (repo) & DNF_REPO_ENABLED_PACKAGES; 129 | if (opt_all || (opt_enabled && enabled) || (opt_disabled && !enabled)) 130 | { 131 | const gchar * id = dnf_repo_get_id (repo); 132 | g_autofree gchar * descr = dnf_repo_get_description (repo); 133 | add_line_into_table (table, opt_all, id, descr, enabled); 134 | } 135 | } 136 | 137 | struct libscols_column *cl = scols_table_get_column (table, COL_REPO_ID); 138 | scols_sort_table (table, cl); 139 | scols_print_table (table); 140 | scols_unref_table (table); 141 | 142 | return TRUE; 143 | } 144 | 145 | static void 146 | dnf_command_repolist_class_init (DnfCommandRepolistClass *klass) 147 | { 148 | } 149 | 150 | static void 151 | dnf_command_repolist_iface_init (DnfCommandInterface *iface) 152 | { 153 | iface->run = dnf_command_repolist_run; 154 | } 155 | 156 | static void 157 | dnf_command_repolist_class_finalize (DnfCommandRepolistClass *klass) 158 | { 159 | } 160 | 161 | G_MODULE_EXPORT void 162 | dnf_command_repolist_register_types (PeasObjectModule *module) 163 | { 164 | dnf_command_repolist_register_type (G_TYPE_MODULE (module)); 165 | 166 | peas_object_module_register_extension_type (module, 167 | DNF_TYPE_COMMAND, 168 | DNF_TYPE_COMMAND_REPOLIST); 169 | } 170 | -------------------------------------------------------------------------------- /dnf/plugins/reinstall/dnf-command-reinstall.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "dnf-command-reinstall.h" 22 | #include "dnf-utils.h" 23 | 24 | struct _DnfCommandReinstall 25 | { 26 | PeasExtensionBase parent_instance; 27 | }; 28 | 29 | static void dnf_command_reinstall_iface_init (DnfCommandInterface *iface); 30 | 31 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandReinstall, 32 | dnf_command_reinstall, 33 | PEAS_TYPE_EXTENSION_BASE, 34 | 0, 35 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 36 | dnf_command_reinstall_iface_init)) 37 | 38 | static void 39 | dnf_command_reinstall_init (DnfCommandReinstall *self) 40 | { 41 | } 42 | 43 | static gint 44 | compare_nevra (gconstpointer a, gconstpointer b, gpointer user_data) 45 | { 46 | return g_strcmp0 (a, b); 47 | } 48 | 49 | static void 50 | packageset_free (gpointer pkg_set) 51 | { 52 | dnf_packageset_free (pkg_set); 53 | } 54 | 55 | static gboolean 56 | dnf_command_reinstall_arg (DnfContext *ctx, const char *arg, GError **error) 57 | { 58 | DnfSack *sack = dnf_context_get_sack (ctx); 59 | 60 | g_auto(HySubject) subject = hy_subject_create (arg); 61 | HyNevra out_nevra; 62 | hy_autoquery HyQuery query = hy_subject_get_best_solution (subject, sack, NULL, &out_nevra, 63 | FALSE, TRUE, TRUE, TRUE, TRUE); 64 | if (out_nevra) 65 | hy_nevra_free (out_nevra); 66 | 67 | hy_autoquery HyQuery query_installed = hy_query_clone (query); 68 | hy_query_filter (query_installed, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME); 69 | g_autoptr(GPtrArray) installed_pkgs = hy_query_run (query_installed); 70 | 71 | hy_query_filter (query, HY_PKG_REPONAME, HY_NEQ, HY_SYSTEM_REPO_NAME); 72 | g_autoptr(GPtrArray) available_pkgs = hy_query_run (query); 73 | 74 | if (installed_pkgs->len == 0) 75 | { 76 | if (available_pkgs->len == 0) 77 | { 78 | g_print ("No match for argument: %s\n", arg); 79 | } 80 | else 81 | { 82 | g_print ("Package for argument %s available, but not installed.\n", arg); 83 | } 84 | return TRUE; 85 | } 86 | 87 | g_autoptr(GTree) available_nevra2pkg_set = g_tree_new_full (compare_nevra, NULL, 88 | g_free, packageset_free); 89 | for (guint i = 0; i < available_pkgs->len; ++i) 90 | { 91 | DnfPackage *package = available_pkgs->pdata[i]; 92 | const char *nevra = dnf_package_get_nevra (package); 93 | DnfPackageSet *pkg_set = g_tree_lookup (available_nevra2pkg_set, nevra); 94 | if (!pkg_set) 95 | { 96 | pkg_set = dnf_packageset_new (sack); 97 | /* dnf_package_get_nevra() returns pointer to temporary buffer -> copy is needed */ 98 | g_tree_insert (available_nevra2pkg_set, g_strdup (nevra), pkg_set); 99 | } 100 | dnf_packageset_add (pkg_set, package); 101 | } 102 | 103 | HyGoal goal = dnf_context_get_goal (ctx); 104 | for (guint i = 0; i < installed_pkgs->len; ++i) 105 | { 106 | DnfPackage *package = installed_pkgs->pdata[i]; 107 | const char *nevra = dnf_package_get_nevra (package); 108 | DnfPackageSet *available_pkgs = g_tree_lookup (available_nevra2pkg_set, nevra); 109 | if (available_pkgs) { 110 | g_auto(HySelector) selector = hy_selector_create (sack); 111 | hy_selector_pkg_set (selector, available_pkgs); 112 | if (!hy_goal_install_selector (goal, selector, error)) 113 | return FALSE; 114 | } 115 | else 116 | g_print ("Installed package %s not available.\n", nevra); 117 | } 118 | 119 | return TRUE; 120 | } 121 | 122 | static gboolean 123 | dnf_command_reinstall_run (DnfCommand *cmd, 124 | int argc, 125 | char *argv[], 126 | GOptionContext *opt_ctx, 127 | DnfContext *ctx, 128 | GError **error) 129 | { 130 | g_auto(GStrv) pkgs = NULL; 131 | const GOptionEntry opts[] = { 132 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &pkgs, NULL, NULL }, 133 | { NULL } 134 | }; 135 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 136 | 137 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 138 | return FALSE; 139 | 140 | if (pkgs == NULL) 141 | { 142 | g_set_error_literal (error, 143 | G_IO_ERROR, 144 | G_IO_ERROR_FAILED, 145 | "Packages are not specified"); 146 | return FALSE; 147 | } 148 | 149 | DnfState * state = dnf_context_get_state (ctx); 150 | if (!dnf_context_setup_sack_with_flags (ctx, state, DNF_CONTEXT_SETUP_SACK_FLAG_NONE, error)) { 151 | return FALSE; 152 | } 153 | 154 | for (GStrv pkg = pkgs; *pkg != NULL; pkg++) 155 | { 156 | if (!dnf_command_reinstall_arg (ctx, *pkg, error)) 157 | return FALSE; 158 | } 159 | 160 | DnfGoalActions flags = DNF_INSTALL; 161 | if (!dnf_context_get_install_weak_deps ()) 162 | flags |= DNF_IGNORE_WEAK_DEPS; 163 | if (!dnf_goal_depsolve (dnf_context_get_goal (ctx), flags, error)) 164 | return FALSE; 165 | 166 | DnfTransaction *transaction = dnf_context_get_transaction (ctx); 167 | int tsflags = dnf_transaction_get_flags (transaction); 168 | dnf_transaction_set_flags(transaction, tsflags | DNF_TRANSACTION_FLAG_ALLOW_REINSTALL); 169 | 170 | if (!dnf_utils_print_transaction (ctx)) 171 | return TRUE; 172 | if (!dnf_utils_userconfirm ()) 173 | return FALSE; 174 | if (!dnf_context_run (ctx, NULL, error)) 175 | return FALSE; 176 | 177 | g_print ("Complete.\n"); 178 | 179 | return TRUE; 180 | } 181 | 182 | static void 183 | dnf_command_reinstall_class_init (DnfCommandReinstallClass *klass) 184 | { 185 | } 186 | 187 | static void 188 | dnf_command_reinstall_iface_init (DnfCommandInterface *iface) 189 | { 190 | iface->run = dnf_command_reinstall_run; 191 | } 192 | 193 | static void 194 | dnf_command_reinstall_class_finalize (DnfCommandReinstallClass *klass) 195 | { 196 | } 197 | 198 | G_MODULE_EXPORT void 199 | dnf_command_reinstall_register_types (PeasObjectModule *module) 200 | { 201 | dnf_command_reinstall_register_type (G_TYPE_MODULE (module)); 202 | 203 | peas_object_module_register_extension_type (module, 204 | DNF_TYPE_COMMAND, 205 | DNF_TYPE_COMMAND_REINSTALL); 206 | } 207 | -------------------------------------------------------------------------------- /dnf/plugins/repoquery/dnf-command-repoquery.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Red Hat, Inc. 3 | * 4 | * Licensed under the GNU Lesser General Public License Version 2.1 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "dnf-command-repoquery.h" 22 | 23 | #include 24 | 25 | struct _DnfCommandRepoquery 26 | { 27 | PeasExtensionBase parent_instance; 28 | }; 29 | 30 | static void dnf_command_repoquery_iface_init (DnfCommandInterface *iface); 31 | 32 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandRepoquery, 33 | dnf_command_repoquery, 34 | PEAS_TYPE_EXTENSION_BASE, 35 | 0, 36 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 37 | dnf_command_repoquery_iface_init)) 38 | 39 | static void 40 | dnf_command_repoquery_init (DnfCommandRepoquery *self) 41 | { 42 | } 43 | 44 | static void 45 | disable_available_repos (DnfContext *ctx) 46 | { 47 | GPtrArray *repos = dnf_context_get_repos (ctx); 48 | for (guint i = 0; i < repos->len; ++i) 49 | { 50 | DnfRepo * repo = g_ptr_array_index (repos, i); 51 | dnf_repo_set_enabled (repo, DNF_REPO_ENABLED_NONE); 52 | } 53 | } 54 | 55 | static gint 56 | gptrarr_dnf_package_cmp (gconstpointer a, gconstpointer b) 57 | { 58 | return dnf_package_cmp(*(DnfPackage**)a, *(DnfPackage**)b); 59 | } 60 | 61 | static void 62 | package_info_add_line (struct libscols_table *table, const char *key, const char *value) 63 | { 64 | struct libscols_line *ln = scols_table_new_line (table, NULL); 65 | scols_line_set_data (ln, 0, key); 66 | scols_line_set_data (ln, 1, value); 67 | } 68 | 69 | static void 70 | print_package_info (DnfPackage *package) 71 | { 72 | struct libscols_table *table = scols_new_table (); 73 | scols_table_enable_noheadings (table, 1); 74 | scols_table_set_column_separator (table, " : "); 75 | scols_table_new_column (table, "key", 5, 0); 76 | struct libscols_column *cl = scols_table_new_column (table, "value", 10, SCOLS_FL_WRAP); 77 | scols_column_set_safechars (cl, "\n"); 78 | scols_column_set_wrapfunc (cl, scols_wrapnl_chunksize, scols_wrapnl_nextchunk, NULL); 79 | 80 | package_info_add_line (table, "Name", dnf_package_get_name (package)); 81 | guint64 epoch = dnf_package_get_epoch (package); 82 | if (epoch != 0) 83 | { 84 | g_autofree gchar *str_epoch = g_strdup_printf ("%ld", epoch); 85 | package_info_add_line (table, "Epoch", str_epoch); 86 | } 87 | package_info_add_line (table, "Version", dnf_package_get_version (package)); 88 | package_info_add_line (table, "Release", dnf_package_get_release (package)); 89 | package_info_add_line (table, "Architecture", dnf_package_get_arch (package)); 90 | g_autofree gchar *size = g_format_size_full (dnf_package_get_size (package), 91 | G_FORMAT_SIZE_LONG_FORMAT | G_FORMAT_SIZE_IEC_UNITS); 92 | package_info_add_line (table, "Size", size); 93 | package_info_add_line (table, "Source", dnf_package_get_sourcerpm (package)); 94 | package_info_add_line (table, "Repository", dnf_package_get_reponame (package)); 95 | package_info_add_line (table, "Summary", dnf_package_get_summary (package)); 96 | package_info_add_line (table, "URL", dnf_package_get_url (package)); 97 | package_info_add_line (table, "License", dnf_package_get_license (package)); 98 | package_info_add_line (table, "Description", dnf_package_get_description (package)); 99 | 100 | scols_print_table (table); 101 | scols_unref_table (table); 102 | } 103 | 104 | static gboolean 105 | dnf_command_repoquery_run (DnfCommand *cmd, 106 | int argc, 107 | char *argv[], 108 | GOptionContext *opt_ctx, 109 | DnfContext *ctx, 110 | GError **error) 111 | { 112 | gboolean opt_available = FALSE; 113 | gboolean opt_info = FALSE; 114 | gboolean opt_installed = FALSE; 115 | gboolean opt_nevra = FALSE; 116 | g_auto(GStrv) opt_key = NULL; 117 | const GOptionEntry opts[] = { 118 | { "available", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_available, "display available packages (default)", NULL }, 119 | { "info", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_info, "show detailed information about the packages", NULL }, 120 | { "installed", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_installed, "display installed packages", NULL }, 121 | { "nevra", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_nevra, 122 | "use name-epoch:version-release.architecture format for displaying packages (default)", NULL }, 123 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_key, NULL, NULL }, 124 | { NULL } 125 | }; 126 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 127 | 128 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 129 | return FALSE; 130 | 131 | // --available is default (compatibility with YUM/DNF) 132 | if (!opt_available && !opt_installed) 133 | opt_available = TRUE; 134 | 135 | if (opt_available && opt_installed) 136 | opt_available = opt_installed = FALSE; 137 | 138 | if (opt_installed) 139 | disable_available_repos (ctx); 140 | 141 | DnfState * state = dnf_context_get_state (ctx); 142 | DnfContextSetupSackFlags sack_flags = opt_available ? DNF_CONTEXT_SETUP_SACK_FLAG_SKIP_RPMDB 143 | : DNF_CONTEXT_SETUP_SACK_FLAG_NONE; 144 | if (!dnf_context_setup_sack_with_flags (ctx, state, sack_flags, error)) { 145 | return FALSE; 146 | } 147 | DnfSack *sack = dnf_context_get_sack (ctx); 148 | 149 | hy_autoquery HyQuery query = hy_query_create (sack); 150 | 151 | if (opt_key) 152 | { 153 | hy_query_filter_empty (query); 154 | for (char **pkey = opt_key; *pkey; ++pkey) 155 | { 156 | g_auto(HySubject) subject = hy_subject_create (*pkey); 157 | HyNevra out_nevra; 158 | hy_autoquery HyQuery key_query = hy_subject_get_best_solution (subject, sack, NULL, 159 | &out_nevra, TRUE, TRUE, FALSE, TRUE, TRUE); 160 | if (out_nevra) 161 | hy_nevra_free(out_nevra); 162 | hy_query_union (query, key_query); 163 | } 164 | } 165 | 166 | g_autoptr(GPtrArray) pkgs = hy_query_run (query); 167 | 168 | g_ptr_array_sort (pkgs, gptrarr_dnf_package_cmp); 169 | 170 | const char *prev_line = ""; 171 | for (guint i = 0; i < pkgs->len; ++i) 172 | { 173 | DnfPackage *package = g_ptr_array_index (pkgs, i); 174 | if (opt_nevra || !opt_info) 175 | { 176 | const char * line = dnf_package_get_nevra (package); 177 | // print nevras without duplicated lines 178 | if (opt_info || strcmp (line, prev_line) != 0) 179 | { 180 | g_print ("%s\n", line); 181 | prev_line = line; 182 | } 183 | } 184 | if (opt_info) 185 | { 186 | print_package_info (package); 187 | g_print ("\n"); 188 | } 189 | } 190 | 191 | return TRUE; 192 | } 193 | 194 | static void 195 | dnf_command_repoquery_class_init (DnfCommandRepoqueryClass *klass) 196 | { 197 | } 198 | 199 | static void 200 | dnf_command_repoquery_iface_init (DnfCommandInterface *iface) 201 | { 202 | iface->run = dnf_command_repoquery_run; 203 | } 204 | 205 | static void 206 | dnf_command_repoquery_class_finalize (DnfCommandRepoqueryClass *klass) 207 | { 208 | } 209 | 210 | G_MODULE_EXPORT void 211 | dnf_command_repoquery_register_types (PeasObjectModule *module) 212 | { 213 | dnf_command_repoquery_register_type (G_TYPE_MODULE (module)); 214 | 215 | peas_object_module_register_extension_type (module, 216 | DNF_TYPE_COMMAND, 217 | DNF_TYPE_COMMAND_REPOQUERY); 218 | } 219 | -------------------------------------------------------------------------------- /dnf/dnf-utils.c: -------------------------------------------------------------------------------- 1 | /* dnf-utils.c 2 | * 3 | * Copyright © 2010-2015 Richard Hughes 4 | * Copyright © 2016 Colin Walters 5 | * Copyright © 2016-2017 Igor Gnatenko 6 | * Copyright © 2017-2020 Jaroslav Rohel 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | #include "dnf-utils.h" 23 | #include 24 | 25 | 26 | // transaction details columns 27 | enum { COL_NEVRA, COL_REPO, COL_SIZE }; 28 | 29 | 30 | static gint 31 | dnf_package_cmp_cb (DnfPackage **pkg1, DnfPackage **pkg2) 32 | { 33 | return dnf_package_cmp (*pkg1, *pkg2); 34 | } 35 | 36 | 37 | static void 38 | dnf_utils_add_transaction_packages (DnfContext *ctx, 39 | struct libscols_table *tb, 40 | struct libscols_line *parent, 41 | GPtrArray *pkgs) 42 | { 43 | // sort packages by NEVRA 44 | g_ptr_array_sort (pkgs, (GCompareFunc) dnf_package_cmp_cb); 45 | 46 | HyGoal goal = dnf_context_get_goal (ctx); 47 | for (guint i = 0; i < pkgs->len; i++) 48 | { 49 | DnfPackage *pkg = pkgs->pdata[i]; 50 | 51 | struct libscols_line *ln = scols_table_new_line (tb, parent); 52 | scols_line_set_data (ln, COL_NEVRA, dnf_package_get_nevra (pkg)); 53 | scols_line_set_data (ln, COL_REPO, dnf_package_get_reponame (pkg)); 54 | g_autofree gchar *formatted_pkg_size = g_format_size (dnf_package_get_size (pkg)); 55 | g_auto(GStrv) formatted_pkg_size_parts = g_strsplit (formatted_pkg_size, "\xC2\xA0", -1); 56 | g_autofree gchar *formatted_pkg_size_simple_spaces = g_strjoinv (" ", formatted_pkg_size_parts); 57 | scols_line_set_data (ln, COL_SIZE, formatted_pkg_size_simple_spaces); 58 | 59 | if (dnf_package_get_action (pkg) != DNF_STATE_ACTION_REMOVE) 60 | { 61 | g_autoptr(GPtrArray) pkgs_replaced = hy_goal_list_obsoleted_by_package (goal, pkg); 62 | g_ptr_array_sort (pkgs_replaced, (GCompareFunc) dnf_package_cmp_cb); 63 | for (guint i = 0; i < pkgs_replaced->len; i++) 64 | { 65 | DnfPackage *pkg = pkgs_replaced->pdata[i]; 66 | struct libscols_line *replacing_ln = scols_table_new_line (tb, ln); 67 | g_autofree gchar *replacing_text = g_strconcat ("replacing ", dnf_package_get_nevra (pkg), NULL); 68 | scols_line_set_data (replacing_ln, COL_NEVRA, replacing_text); 69 | } 70 | } 71 | } 72 | } 73 | 74 | 75 | gboolean 76 | dnf_utils_conf_main_get_bool_opt (const gchar *name, enum DnfConfPriority *priority) 77 | { 78 | g_autofree gchar *tmp = dnf_conf_main_get_option (name, priority, NULL); 79 | return tmp != NULL && (*tmp == '1' || *tmp == 'y' || *tmp == 'Y'); 80 | } 81 | 82 | 83 | gboolean 84 | dnf_utils_userconfirm (void) 85 | { 86 | gboolean ret; 87 | enum DnfConfPriority priority; 88 | 89 | // "assumeno" takes precedence over "assumeyes" 90 | if (dnf_utils_conf_main_get_bool_opt ("assumeno", &priority)) 91 | ret = FALSE; 92 | else if (dnf_utils_conf_main_get_bool_opt ("assumeyes", &priority)) 93 | ret = TRUE; 94 | else 95 | { 96 | gboolean defaultyes = dnf_utils_conf_main_get_bool_opt ("defaultyes", &priority); 97 | 98 | const char *msg; 99 | if (defaultyes) 100 | msg = "Is this ok [Y/n]: "; 101 | else 102 | msg = "Is this ok [y/N]: "; 103 | 104 | while (TRUE) 105 | { 106 | g_print ("%s", msg); 107 | 108 | char choice = getchar (); 109 | if (choice == '\n' || choice == '\r') 110 | { 111 | ret = defaultyes; 112 | break; 113 | } 114 | 115 | char second = getchar (); 116 | for (char ch = second; ch != '\n'; ch = getchar ()) 117 | ; 118 | 119 | if (second == '\n' || second == '\r') 120 | { 121 | if (choice == 'y' || choice == 'Y') 122 | { 123 | ret = TRUE; 124 | break; 125 | } 126 | if (choice == 'n' || choice == 'N') 127 | { 128 | ret = FALSE; 129 | break; 130 | } 131 | } 132 | } 133 | } 134 | 135 | if (!ret) 136 | g_print ("Operation aborted.\n"); 137 | 138 | return ret; 139 | } 140 | 141 | gboolean 142 | dnf_utils_print_transaction (DnfContext *ctx) 143 | { 144 | g_autoptr(GPtrArray) pkgs = dnf_goal_get_packages (dnf_context_get_goal (ctx), 145 | DNF_PACKAGE_INFO_INSTALL, 146 | DNF_PACKAGE_INFO_REINSTALL, 147 | DNF_PACKAGE_INFO_DOWNGRADE, 148 | DNF_PACKAGE_INFO_UPDATE, 149 | DNF_PACKAGE_INFO_REMOVE, 150 | -1); 151 | 152 | if (pkgs->len == 0) 153 | { 154 | g_autofree char * report = dnf_context_get_module_report (ctx); 155 | if (report) 156 | { 157 | g_print ("%s\n", report); 158 | return TRUE; 159 | } else { 160 | g_print ("Nothing to do.\n"); 161 | return FALSE; 162 | } 163 | } 164 | 165 | struct libscols_line *ln; 166 | 167 | struct libscols_table *tb = scols_new_table (); 168 | scols_table_new_column (tb, "Package", 0.7, SCOLS_FL_TREE); 169 | scols_table_new_column (tb, "Repository", 0.2, SCOLS_FL_TRUNC); 170 | scols_table_new_column (tb, "Size", 0.1, SCOLS_FL_RIGHT); 171 | scols_table_enable_maxout (tb, 1); 172 | struct libscols_symbols *sb = scols_new_symbols (); 173 | scols_symbols_set_branch (sb, " "); 174 | scols_symbols_set_right (sb, " "); 175 | scols_symbols_set_vertical (sb, " "); 176 | scols_table_set_symbols (tb, sb); 177 | 178 | g_autoptr(GPtrArray) pkgs_install = dnf_goal_get_packages (dnf_context_get_goal (ctx), 179 | DNF_PACKAGE_INFO_INSTALL, 180 | -1); 181 | if (pkgs_install->len != 0) 182 | { 183 | ln = scols_table_new_line (tb, NULL); 184 | scols_line_set_data (ln, COL_NEVRA, "Installing:"); 185 | dnf_utils_add_transaction_packages (ctx, tb, ln, pkgs_install); 186 | } 187 | 188 | g_autoptr(GPtrArray) pkgs_reinstall = dnf_goal_get_packages (dnf_context_get_goal (ctx), 189 | DNF_PACKAGE_INFO_REINSTALL, 190 | -1); 191 | if (pkgs_reinstall->len != 0) 192 | { 193 | ln = scols_table_new_line (tb, NULL); 194 | scols_line_set_data (ln, COL_NEVRA, "Reinstalling:"); 195 | dnf_utils_add_transaction_packages (ctx, tb, ln, pkgs_reinstall); 196 | } 197 | 198 | g_autoptr(GPtrArray) pkgs_upgrade = dnf_goal_get_packages (dnf_context_get_goal (ctx), 199 | DNF_PACKAGE_INFO_UPDATE, 200 | -1); 201 | if (pkgs_upgrade->len != 0) 202 | { 203 | ln = scols_table_new_line (tb, NULL); 204 | scols_line_set_data (ln, COL_NEVRA, "Upgrading:"); 205 | dnf_utils_add_transaction_packages (ctx, tb, ln, pkgs_upgrade); 206 | } 207 | 208 | g_autoptr(GPtrArray) pkgs_obsolete = dnf_goal_get_packages (dnf_context_get_goal (ctx), 209 | DNF_PACKAGE_INFO_OBSOLETE, 210 | -1); 211 | 212 | g_autoptr(GPtrArray) pkgs_remove = dnf_goal_get_packages (dnf_context_get_goal (ctx), 213 | DNF_PACKAGE_INFO_REMOVE, 214 | -1); 215 | if (pkgs_remove->len != 0) 216 | { 217 | ln = scols_table_new_line (tb, NULL); 218 | scols_line_set_data (ln, COL_NEVRA, "Removing:"); 219 | dnf_utils_add_transaction_packages (ctx, tb, ln, pkgs_remove); 220 | } 221 | 222 | g_autoptr(GPtrArray) pkgs_downgrade = dnf_goal_get_packages (dnf_context_get_goal (ctx), 223 | DNF_PACKAGE_INFO_DOWNGRADE, 224 | -1); 225 | if (pkgs_downgrade->len != 0) 226 | { 227 | ln = scols_table_new_line (tb, NULL); 228 | scols_line_set_data (ln, COL_NEVRA, "Downgrading:"); 229 | dnf_utils_add_transaction_packages (ctx, tb, ln, pkgs_downgrade); 230 | } 231 | 232 | scols_print_table (tb); 233 | scols_unref_symbols (sb); 234 | scols_unref_table (tb); 235 | 236 | g_print ("Transaction Summary:\n"); 237 | g_print (" %-15s %4d packages\n", "Installing:", pkgs_install->len); 238 | g_print (" %-15s %4d packages\n", "Reinstalling:", pkgs_reinstall->len); 239 | g_print (" %-15s %4d packages\n", "Upgrading:", pkgs_upgrade->len); 240 | g_print (" %-15s %4d packages\n", "Obsoleting:", pkgs_obsolete->len); 241 | g_print (" %-15s %4d packages\n", "Removing:", pkgs_remove->len); 242 | g_print (" %-15s %4d packages\n", "Downgrading:", pkgs_downgrade->len); 243 | 244 | g_autofree char * report = dnf_context_get_module_report (ctx); 245 | if (report) 246 | { 247 | g_print ("%s\n", report); 248 | } 249 | /* check for test mode */ 250 | DnfTransaction *txn = dnf_context_get_transaction (ctx); 251 | if (dnf_transaction_get_flags (txn) & DNF_TRANSACTION_FLAG_TEST) 252 | g_print ("Test mode enabled: Microdnf will only download packages, install gpg keys, and check the transaction.\n"); 253 | 254 | return TRUE; 255 | } 256 | -------------------------------------------------------------------------------- /dnf/plugins/leaves/dnf-command-leaves.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-leaves.c 2 | * 3 | * Copyright © 2022 Emil Renner Berthing 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include "dnf-command-leaves.h" 20 | 21 | typedef struct { 22 | guint len; 23 | guint idx[]; 24 | } IdxArray; 25 | 26 | static IdxArray * 27 | idx_array_new (guint len) 28 | { 29 | return g_malloc0 (G_STRUCT_OFFSET (IdxArray, idx) + len * sizeof (guint)); 30 | } 31 | 32 | static void 33 | idx_array_add (IdxArray *arr, guint idx) 34 | { 35 | arr->idx[arr->len++] = idx; 36 | } 37 | 38 | static gboolean 39 | idx_array_from_set_iter (gpointer key, gpointer value, gpointer user_data) 40 | { 41 | IdxArray *arr = user_data; 42 | idx_array_add (arr, GPOINTER_TO_UINT (key)); 43 | return TRUE; 44 | } 45 | 46 | static gint 47 | idx_array_compare_func (gconstpointer a, gconstpointer b, gpointer user_data) 48 | { 49 | guint x = *(const guint *)a; 50 | guint y = *(const guint *)b; 51 | 52 | if (x < y) 53 | return -1; 54 | return x > y; 55 | } 56 | 57 | static IdxArray * 58 | idx_array_copy (const guint *idx, guint len) 59 | { 60 | IdxArray *arr = idx_array_new (len); 61 | arr->len = len; 62 | for (guint i = 0; i < len; i++) 63 | arr->idx[i] = idx[i]; 64 | g_qsort_with_data (arr->idx, arr->len, sizeof (*arr->idx), idx_array_compare_func, NULL); 65 | return arr; 66 | } 67 | 68 | static IdxArray * 69 | idx_array_from_set (GHashTable *set) 70 | { 71 | IdxArray *arr = idx_array_new (g_hash_table_size (set)); 72 | g_hash_table_foreach_remove (set, idx_array_from_set_iter, arr); 73 | g_qsort_with_data (arr->idx, arr->len, sizeof (*arr->idx), idx_array_compare_func, NULL); 74 | return arr; 75 | } 76 | 77 | static gint 78 | gtree_dnf_package_cmp (gconstpointer a, gconstpointer b) 79 | { 80 | return dnf_package_cmp ((DnfPackage *)a, (DnfPackage *)b); 81 | } 82 | 83 | static void 84 | add_edges (GHashTable *edges, HyQuery query, GTree *pkg2idx, DnfReldepList *deps) 85 | { 86 | const gint ndeps = dnf_reldep_list_count (deps); 87 | 88 | // resolve dependencies and add an edge if there is exactly one package satisfying it 89 | for (gint j = 0; j < ndeps; j++) 90 | { 91 | DnfReldep *dep = dnf_reldep_list_index (deps, j); 92 | 93 | hy_query_filter_reldep (query, HY_PKG_PROVIDES, dep); 94 | g_autoptr(GPtrArray) ppkgs = hy_query_run (query); 95 | hy_query_clear (query); 96 | dnf_reldep_free (dep); 97 | 98 | if (ppkgs->len != 1) 99 | continue; 100 | 101 | const DnfPackage *ppkg = g_ptr_array_index (ppkgs, 0); 102 | GTreeNode *node = g_tree_lookup_node (pkg2idx, ppkg);; 103 | g_assert (node); 104 | g_hash_table_insert (edges, g_tree_node_value (node), NULL); 105 | } 106 | 107 | dnf_reldep_list_free (deps); 108 | } 109 | 110 | static GPtrArray * 111 | build_graph (HyQuery query, const GPtrArray *pkgs, gboolean recommends) 112 | { 113 | // create pkg2idx to map DnfPackages to their index in pkgs 114 | g_autoptr(GTree) pkg2idx = g_tree_new (gtree_dnf_package_cmp); 115 | for (guint i = 0; i < pkgs->len; i++) 116 | { 117 | DnfPackage *pkg = g_ptr_array_index (pkgs, i); 118 | g_tree_insert (pkg2idx, pkg, GUINT_TO_POINTER (i)); 119 | } 120 | 121 | GPtrArray *graph = g_ptr_array_new_full (pkgs->len, g_free); 122 | g_autoptr(GHashTable) edges = g_hash_table_new (g_direct_hash, g_direct_equal); 123 | 124 | for (guint i = 0; i < pkgs->len; i++) 125 | { 126 | DnfPackage *pkg = g_ptr_array_index (pkgs, i); 127 | add_edges (edges, query, pkg2idx, dnf_package_get_requires (pkg)); 128 | if (recommends) 129 | add_edges (edges, query, pkg2idx, dnf_package_get_recommends (pkg)); 130 | g_hash_table_remove (edges, GUINT_TO_POINTER (i)); // remove self-edges 131 | g_ptr_array_add (graph, idx_array_from_set (edges)); 132 | } 133 | 134 | return graph; 135 | } 136 | 137 | static GPtrArray * 138 | reverse_graph (const GPtrArray *graph) 139 | { 140 | g_autofree guint *len = g_malloc0 (graph->len * sizeof (*len)); 141 | 142 | for (guint i = 0; i < graph->len; i++) 143 | { 144 | const IdxArray *edges = g_ptr_array_index (graph, i); 145 | 146 | for (guint j = 0; j < edges->len; j++) 147 | len[edges->idx[j]]++; 148 | } 149 | 150 | GPtrArray *rgraph = g_ptr_array_new_full (graph->len, g_free); 151 | for (guint i = 0; i < graph->len; i++) 152 | g_ptr_array_add (rgraph, idx_array_new (len[i])); 153 | 154 | for (guint i = 0; i < graph->len; i++) 155 | { 156 | const IdxArray *edges = g_ptr_array_index (graph, i); 157 | 158 | for (guint j = 0; j < edges->len; j++) 159 | { 160 | IdxArray *redges = g_ptr_array_index (rgraph, edges->idx[j]); 161 | idx_array_add (redges, i); 162 | } 163 | } 164 | 165 | return rgraph; 166 | } 167 | 168 | static GPtrArray * 169 | kosaraju (const GPtrArray *graph) 170 | { 171 | const guint N = graph->len; 172 | g_autofree guint *rstack = g_malloc (N * sizeof (*rstack)); 173 | g_autofree guint *stack = g_malloc (N * sizeof (*stack)); 174 | g_autofree gboolean *tag = g_malloc0 (N * sizeof (*tag)); 175 | guint r = N; 176 | guint top = 0; 177 | 178 | // do depth-first searches in the graph and push nodes to rstack 179 | // "on the way up" until all nodes have been pushed. 180 | // tag nodes as they're processed so we don't visit them more than once 181 | for (guint i = 0; i < N; i++) 182 | { 183 | if (tag[i]) 184 | continue; 185 | 186 | guint u = i; 187 | guint j = 0; 188 | tag[u] = TRUE; 189 | while (true) 190 | { 191 | const IdxArray *edges = g_ptr_array_index (graph, u); 192 | if (j < edges->len) 193 | { 194 | const guint v = edges->idx[j++]; 195 | if (!tag[v]) 196 | { 197 | rstack[top] = j; 198 | stack[top++] = u; 199 | u = v; 200 | j = 0; 201 | tag[u] = TRUE; 202 | } 203 | } 204 | else 205 | { 206 | rstack[--r] = u; 207 | if (!top) 208 | break; 209 | u = stack[--top]; 210 | j = rstack[top]; 211 | } 212 | } 213 | } 214 | g_assert (r == 0); 215 | 216 | // now searches beginning at nodes popped from rstack in the graph with all 217 | // edges reversed will give us the strongly connected components. 218 | // this time all nodes are tagged, so let's remove the tags as we visit each 219 | // node. 220 | // the incoming edges to each component is the union of incoming edges to 221 | // each node in the component minus the incoming edges from component nodes 222 | // themselves. 223 | // if there are no such incoming edges the component is a leaf and we 224 | // add it to the array of leaves. 225 | g_autoptr(GPtrArray) rgraph = reverse_graph (graph); 226 | g_autoptr(GHashTable) sccredges = g_hash_table_new (g_direct_hash, g_direct_equal); 227 | GPtrArray *leaves = g_ptr_array_new_with_free_func (g_free); 228 | for (; r < N; r++) 229 | { 230 | guint u = rstack[r]; 231 | if (!tag[u]) 232 | continue; 233 | 234 | stack[top++] = u; 235 | tag[u] = FALSE; 236 | guint s = N; 237 | while (top) 238 | { 239 | u = stack[--s] = stack[--top]; 240 | const IdxArray *redges = g_ptr_array_index (rgraph, u); 241 | for (guint j = 0; j < redges->len; j++) 242 | { 243 | const guint v = redges->idx[j]; 244 | g_hash_table_insert (sccredges, GUINT_TO_POINTER (v), NULL); 245 | if (!tag[v]) 246 | continue; 247 | 248 | stack[top++] = v; 249 | tag[v] = FALSE; 250 | } 251 | } 252 | 253 | for (guint i = s; i < N; i++) 254 | g_hash_table_remove (sccredges, GUINT_TO_POINTER (stack[i])); 255 | 256 | if (g_hash_table_size (sccredges) == 0) 257 | g_ptr_array_add (leaves, idx_array_copy (&stack[s], N - s)); 258 | else 259 | g_hash_table_remove_all (sccredges); 260 | } 261 | 262 | return leaves; 263 | } 264 | 265 | struct _DnfCommandLeaves 266 | { 267 | PeasExtensionBase parent_instance; 268 | }; 269 | 270 | static void dnf_command_leaves_iface_init (DnfCommandInterface *iface); 271 | 272 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandLeaves, 273 | dnf_command_leaves, 274 | PEAS_TYPE_EXTENSION_BASE, 275 | 0, 276 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 277 | dnf_command_leaves_iface_init)) 278 | 279 | static void 280 | dnf_command_leaves_init (DnfCommandLeaves *self) 281 | { 282 | } 283 | 284 | static void 285 | disable_available_repos (DnfContext *ctx) 286 | { 287 | const GPtrArray *repos = dnf_context_get_repos (ctx); 288 | 289 | for (guint i = 0; i < repos->len; ++i) 290 | { 291 | DnfRepo *repo = g_ptr_array_index (repos, i); 292 | dnf_repo_set_enabled (repo, DNF_REPO_ENABLED_NONE); 293 | } 294 | } 295 | 296 | static gint 297 | gptrarr_dnf_package_cmp (gconstpointer a, gconstpointer b) 298 | { 299 | DnfPackage *const *x = a; 300 | DnfPackage *const *y = b; 301 | return dnf_package_cmp (*x, *y); 302 | } 303 | 304 | static gint 305 | gptrarr_first_package_cmp (gconstpointer a, gconstpointer b) 306 | { 307 | IdxArray *const *x = a; 308 | IdxArray *const *y = b; 309 | guint i = (*x)->idx[0]; 310 | guint j = (*y)->idx[0]; 311 | 312 | if (i < j) 313 | return -1; 314 | return i > j; 315 | } 316 | 317 | static gboolean 318 | dnf_command_leaves_run (DnfCommand *cmd, 319 | int argc, 320 | char *argv[], 321 | GOptionContext *opt_ctx, 322 | DnfContext *ctx, 323 | GError **error) 324 | { 325 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 326 | return FALSE; 327 | 328 | // only look at installed packages 329 | disable_available_repos (ctx); 330 | if (!dnf_context_setup_sack_with_flags (ctx, 331 | dnf_context_get_state (ctx), 332 | DNF_CONTEXT_SETUP_SACK_FLAG_NONE, 333 | error)) { 334 | 335 | return FALSE; 336 | } 337 | 338 | // get a sorted array of all installed packages 339 | hy_autoquery HyQuery query = hy_query_create (dnf_context_get_sack (ctx)); 340 | g_autoptr(GPtrArray) pkgs = hy_query_run (query); 341 | g_ptr_array_sort (pkgs, gptrarr_dnf_package_cmp); 342 | 343 | // build the directed graph of dependencies 344 | g_autoptr(GPtrArray) graph = build_graph (query, pkgs, dnf_context_get_install_weak_deps ()); 345 | 346 | // run Kosaraju's algorithm to find strongly connected components 347 | // withhout any incoming edges 348 | g_autoptr(GPtrArray) leaves = kosaraju (graph); 349 | g_ptr_array_sort (leaves, gptrarr_first_package_cmp); 350 | 351 | // print the packages grouped by their components 352 | for (guint i = 0; i < leaves->len; i++) 353 | { 354 | const IdxArray *scc = g_ptr_array_index (leaves, i); 355 | gchar mark = '-'; 356 | 357 | for (guint j = 0; j < scc->len; j++) 358 | { 359 | DnfPackage *pkg = g_ptr_array_index (pkgs, scc->idx[j]); 360 | g_print ("%c %s\n", mark, dnf_package_get_nevra (pkg)); 361 | mark = ' '; 362 | } 363 | } 364 | 365 | return TRUE; 366 | } 367 | 368 | static void 369 | dnf_command_leaves_class_init (DnfCommandLeavesClass *klass) 370 | { 371 | } 372 | 373 | static void 374 | dnf_command_leaves_iface_init (DnfCommandInterface *iface) 375 | { 376 | iface->run = dnf_command_leaves_run; 377 | } 378 | 379 | static void 380 | dnf_command_leaves_class_finalize (DnfCommandLeavesClass *klass) 381 | { 382 | } 383 | 384 | G_MODULE_EXPORT void 385 | dnf_command_leaves_register_types (PeasObjectModule *module) 386 | { 387 | dnf_command_leaves_register_type (G_TYPE_MODULE (module)); 388 | 389 | peas_object_module_register_extension_type (module, 390 | DNF_TYPE_COMMAND, 391 | DNF_TYPE_COMMAND_LEAVES); 392 | } 393 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /dnf/plugins/download/dnf-command-download.c: -------------------------------------------------------------------------------- 1 | /* dnf-command-download.c 2 | * 3 | * Copyright © 2020-2021 Daniel Hams 4 | * Copyright © 2021 Jaroslav Rohel 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "dnf-command-download.h" 21 | #include "dnf-utils.h" 22 | 23 | /* For MAXPATHLEN */ 24 | #include 25 | 26 | struct _DnfCommandDownload 27 | { 28 | PeasExtensionBase parent_instance; 29 | }; 30 | 31 | static void dnf_command_download_iface_init (DnfCommandInterface *iface); 32 | 33 | G_DEFINE_DYNAMIC_TYPE_EXTENDED (DnfCommandDownload, 34 | dnf_command_download, 35 | PEAS_TYPE_EXTENSION_BASE, 36 | 0, 37 | G_IMPLEMENT_INTERFACE (DNF_TYPE_COMMAND, 38 | dnf_command_download_iface_init)) 39 | 40 | static void 41 | dnf_command_download_init (DnfCommandDownload *self) 42 | { 43 | } 44 | 45 | inline static gboolean 46 | str_ends_with (const gchar * buf, const gchar * val) 47 | { 48 | size_t buf_len = strlen (buf); 49 | size_t val_len = strlen (val); 50 | return buf_len >= val_len && memcmp (buf + buf_len - val_len, val, val_len) == 0; 51 | } 52 | 53 | /* Implements the functionality of the "g_ptr_array_extend_and_steal" function. 54 | * The function was added to glib in version 2.62. We don't want to require a newer glib. */ 55 | static void 56 | ptr_array_extend_and_steal (GPtrArray *array_to_extend, GPtrArray *array) 57 | { 58 | guint origin_len = array_to_extend->len; 59 | g_ptr_array_set_size (array_to_extend, origin_len + array->len); 60 | for (guint i = 0; i < array->len; ++i) 61 | { 62 | g_ptr_array_index (array_to_extend, origin_len + i) = g_ptr_array_index (array, i); 63 | } 64 | array->len = 0; 65 | g_ptr_array_unref (array); 66 | } 67 | 68 | static gboolean dnf_command_download_rewriterepotosrc (gchar * repo_buf) 69 | { 70 | if (str_ends_with (repo_buf, "-rpms")) 71 | { 72 | // Add a terminator in the right place before we strcat 73 | repo_buf[strlen (repo_buf) - 5] = '\0'; 74 | strcat (repo_buf, "-source-rpms"); 75 | return TRUE; 76 | } 77 | else if (!str_ends_with (repo_buf, "-source")) 78 | { 79 | strcat (repo_buf, "-source"); 80 | return TRUE; 81 | } 82 | return FALSE; 83 | } 84 | 85 | static gboolean 86 | dnf_command_download_enablesourcerepos (DnfContext *ctx, 87 | DnfRepoLoader *repo_loader, 88 | GError **error) 89 | { 90 | g_autoptr(GError) local_error = NULL; 91 | // A place where we can "extend" the repoid with an extension 92 | gchar tmp_name[MAXPATHLEN]; 93 | g_autoptr(GPtrArray) all_repos = dnf_repo_loader_get_repos (repo_loader, error); 94 | 95 | // We have to activate repos in a second loop to avoid breaking the iterator 96 | // on the above repo list. We are "strdup"ing strings into it, so need 97 | // free called on them. 98 | g_autoptr(GPtrArray) repos_to_enable = g_ptr_array_new_full (all_repos->len, 99 | free); 100 | // Look for each enabled repo if there is a corresponding source repo 101 | // that we need to enable. 102 | for (guint i = 0 ; i < all_repos->len; ++i ) 103 | { 104 | DnfRepo * repo = g_ptr_array_index (all_repos, i); 105 | const gchar * repo_id = dnf_repo_get_id (repo); 106 | if (dnf_repo_get_enabled (repo)) 107 | { 108 | int repo_id_len = strlen (repo_id); 109 | if (repo_id_len >= (MAXPATHLEN - 1 - strlen ("-source-rpms"))) 110 | { 111 | // Repo name too long when concatenated 112 | g_set_error (error, 113 | DNF_ERROR, 114 | DNF_ERROR_INTERNAL_ERROR, 115 | "Repository name overflow when -source-rpms added (%1$s)", 116 | repo_id); 117 | return FALSE; 118 | } 119 | strcpy (tmp_name, repo_id); 120 | // Only look for an associated source repo where adding an extension 121 | // makes sense 122 | if (dnf_command_download_rewriterepotosrc (tmp_name)) 123 | { 124 | DnfRepo * src_repo = dnf_repo_loader_get_repo_by_id (repo_loader, 125 | tmp_name, 126 | &local_error); 127 | if (local_error != NULL) 128 | { 129 | if (!g_error_matches (local_error, DNF_ERROR, DNF_ERROR_REPO_NOT_FOUND)) 130 | { 131 | g_propagate_error (error, local_error); 132 | return FALSE; 133 | } 134 | // Repo not found is not terminal 135 | g_error_free (local_error); 136 | local_error = NULL; 137 | continue; 138 | } 139 | if (!dnf_repo_get_enabled (src_repo)) 140 | { 141 | // Repo exists and not enabled, add it to our list to enable 142 | g_ptr_array_add (repos_to_enable, strdup (tmp_name)); 143 | } 144 | } 145 | // else repo "source" equiv already enabled or doesn't exist 146 | } 147 | } 148 | 149 | // Repo enable loop 150 | for (guint r = 0 ; r < repos_to_enable->len; ++r) 151 | { 152 | gchar * repo_to_enable_id = g_ptr_array_index (repos_to_enable, r); 153 | if (!dnf_context_repo_enable (ctx, repo_to_enable_id, error)) 154 | { 155 | return FALSE; 156 | } 157 | else 158 | { 159 | g_print ("enabling %s repository\n", repo_to_enable_id); 160 | } 161 | } 162 | return TRUE; 163 | } 164 | 165 | static gint 166 | gptrarr_dnf_package_repopkgcmp (gconstpointer a, gconstpointer b) 167 | { 168 | // Sort by repo first, then by package 169 | // so we only need to add repo keys the first time we see a repo 170 | // in the package list 171 | DnfPackage **apkg = (DnfPackage**)a; 172 | DnfPackage **bpkg = (DnfPackage**)b; 173 | const gchar * areponame = dnf_package_get_reponame (*apkg); 174 | const gchar * breponame = dnf_package_get_reponame (*bpkg); 175 | int repocmp = strcmp (areponame, breponame); 176 | if (repocmp == 0) 177 | { 178 | return dnf_package_cmp (*apkg, *bpkg); 179 | } 180 | return repocmp; 181 | } 182 | 183 | /* Compare packages by repository priority and cost */ 184 | static gint 185 | dnf_package_repo_prio_cost_cmp (gconstpointer pkg1, gconstpointer pkg2, gpointer repo_loader) 186 | { 187 | const gchar *pkg1_reponame = dnf_package_get_reponame ((DnfPackage*)pkg1); 188 | const gchar *pkg2_reponame = dnf_package_get_reponame ((DnfPackage*)pkg2); 189 | if (strcmp (pkg1_reponame, pkg2_reponame) == 0) 190 | return 0; 191 | 192 | DnfRepo *pkg1_repo = dnf_repo_loader_get_repo_by_id (repo_loader, pkg1_reponame, NULL); 193 | DnfRepo *pkg2_repo = dnf_repo_loader_get_repo_by_id (repo_loader, pkg2_reponame, NULL); 194 | 195 | // A higher value means a lower repository priority. 196 | int result = (pkg2_repo ? hy_repo_get_priority (dnf_repo_get_repo (pkg2_repo)) : INT_MAX) - 197 | (pkg1_repo ? hy_repo_get_priority (dnf_repo_get_repo (pkg1_repo)) : INT_MAX); 198 | 199 | if (result == 0) 200 | result = (pkg1_repo ? hy_repo_get_cost (dnf_repo_get_repo (pkg1_repo)) : INT_MAX) - 201 | (pkg2_repo ? hy_repo_get_cost (dnf_repo_get_repo (pkg2_repo)) : INT_MAX); 202 | 203 | return result; 204 | } 205 | 206 | /* The "pkgs" array can contain multiple packages with the same NEVRA. 207 | * The function selects one (from the cheapest repository with the highest priority) package for each NEVRA. */ 208 | static GPtrArray * 209 | select_one_pkg_for_nevra (DnfRepoLoader *repo_loader, GPtrArray *pkgs) 210 | { 211 | g_autoptr(GHashTable) nevra2pkgs = g_hash_table_new (g_str_hash, g_str_equal); 212 | for (guint i = 0 ; i < pkgs->len; ++i) 213 | { 214 | DnfPackage *pkg = g_ptr_array_index (pkgs, i); 215 | const gchar *pkg_nevra = dnf_package_get_nevra (pkg); 216 | g_hash_table_insert (nevra2pkgs, (gpointer)pkg_nevra, g_slist_prepend (g_hash_table_lookup (nevra2pkgs, pkg_nevra), pkg)); 217 | } 218 | 219 | g_autoptr(GPtrArray) pkgs_to_download = g_ptr_array_sized_new (g_hash_table_size (nevra2pkgs)); 220 | GHashTableIter iter; 221 | GSList *pkgs_list; 222 | g_hash_table_iter_init (&iter, nevra2pkgs); 223 | while (g_hash_table_iter_next (&iter, NULL, (gpointer)&pkgs_list)) 224 | { 225 | pkgs_list = g_slist_sort_with_data (pkgs_list, dnf_package_repo_prio_cost_cmp, repo_loader); 226 | g_ptr_array_add (pkgs_to_download, pkgs_list->data); 227 | g_slist_free (pkgs_list); 228 | } 229 | 230 | return g_steal_pointer (&pkgs_to_download); 231 | } 232 | 233 | static gboolean 234 | download_packages (DnfRepoLoader *repo_loader, GPtrArray *pkgs, DnfState *state, GError **error) 235 | { 236 | g_autoptr(GPtrArray) pkgs_to_download = select_one_pkg_for_nevra (repo_loader, pkgs); 237 | 238 | g_ptr_array_sort (pkgs_to_download, gptrarr_dnf_package_repopkgcmp); 239 | rpmKeyring keyring = rpmKeyringNew (); 240 | GError *error_local = NULL; 241 | gchar prev_repo[MAXPATHLEN]; 242 | prev_repo[0] = '\0'; 243 | for (guint i = 0 ; i < pkgs_to_download->len; ++i) 244 | { 245 | DnfPackage * pkg = g_ptr_array_index (pkgs_to_download, i); 246 | const gchar * pkg_nevra = dnf_package_get_nevra (pkg); 247 | 248 | const gchar * reponame = dnf_package_get_reponame (pkg); 249 | if (strlen (reponame) >= MAXPATHLEN) 250 | { 251 | g_error ("Reponame exceeds max path len (%s)\n", reponame); 252 | return FALSE; 253 | } 254 | DnfRepo * repo = dnf_repo_loader_get_repo_by_id (repo_loader, reponame, error); 255 | if (*error != 0) 256 | { 257 | g_print ("Failed to find repo(%s)\n", reponame); 258 | return FALSE; 259 | } 260 | // Add repo keys to keyring if this is the first time we see the repo 261 | if (prev_repo[0] == '\0' || strcmp (prev_repo, reponame) != 0) 262 | { 263 | g_auto(GStrv) pubkeys = dnf_repo_get_public_keys (repo); 264 | if (*pubkeys) 265 | { 266 | for (char **iter = pubkeys; iter && *iter; iter++) 267 | { 268 | const char *pubkey = *iter; 269 | if (!dnf_keyring_add_public_key (keyring, pubkey, error)) 270 | { 271 | return FALSE; 272 | } 273 | } 274 | } 275 | strcpy (prev_repo, reponame); 276 | } 277 | dnf_package_set_repo (pkg, repo); 278 | const gchar *download_path = dnf_package_download (pkg, "./", state, error); 279 | if (*error != 0) 280 | { 281 | g_print ("Failed to download %s\n", pkg_nevra); 282 | return FALSE; 283 | } 284 | 285 | g_print ("Downloaded %s\n", pkg_nevra); 286 | 287 | // Check signature (if set on repo) 288 | if (dnf_repo_get_gpgcheck (repo) && 289 | !dnf_keyring_check_untrusted_file (keyring, download_path, &error_local)) 290 | { 291 | if (!g_error_matches (error_local, DNF_ERROR, DNF_ERROR_GPG_SIGNATURE_INVALID)) 292 | { 293 | g_set_error (error, 294 | DNF_ERROR, 295 | DNF_ERROR_FILE_INVALID, 296 | "keyring check failure on %1$s " 297 | "and repo %2$s is GPG enabled: %3$s", 298 | dnf_package_get_nevra (pkg), 299 | dnf_repo_get_id (repo), 300 | error_local->message); 301 | g_error_free (error_local); 302 | return FALSE; 303 | } 304 | g_set_error (error, 305 | DNF_ERROR, 306 | DNF_ERROR_FILE_INVALID, 307 | "package %1$s cannot be verified " 308 | "and repo %2$s is GPG enabled: %3$s", 309 | dnf_package_get_nevra (pkg), 310 | dnf_repo_get_id (repo), 311 | error_local->message); 312 | g_error_free (error_local); 313 | return FALSE; 314 | } 315 | } 316 | return TRUE; 317 | } 318 | 319 | static HyQuery 320 | get_packages_query (DnfContext *ctx, GStrv pkgs_spec, gboolean opt_src, const gchar *opt_archlist) 321 | { 322 | DnfSack *sack = dnf_context_get_sack (ctx); 323 | hy_autoquery HyQuery query = hy_query_create (sack); 324 | 325 | if (pkgs_spec) 326 | { 327 | hy_query_filter_empty (query); 328 | for (char **pkey = pkgs_spec; *pkey; ++pkey) 329 | { 330 | g_auto(HySubject) subject = hy_subject_create (*pkey); 331 | HyNevra out_nevra; 332 | hy_autoquery HyQuery key_query = 333 | hy_subject_get_best_solution (subject, sack, NULL, &out_nevra, 334 | FALSE, TRUE, TRUE, TRUE, opt_src); 335 | if (out_nevra) 336 | { 337 | hy_nevra_free (out_nevra); 338 | } 339 | hy_query_filter (key_query, HY_PKG_REPONAME, HY_NEQ, HY_SYSTEM_REPO_NAME); 340 | hy_query_filter_num (key_query, HY_PKG_LATEST_PER_ARCH_BY_PRIORITY, HY_EQ, 1); 341 | hy_query_union (query, key_query); 342 | } 343 | } 344 | if (opt_src) 345 | { 346 | hy_query_filter (query, HY_PKG_ARCH, HY_EQ, "src"); 347 | } 348 | 349 | if (opt_archlist) 350 | { 351 | g_auto(GStrv) archs_array = g_strsplit_set (opt_archlist, ", ", -1); 352 | hy_query_filter_in (query, HY_PKG_ARCH, HY_EQ, (const char**)archs_array); 353 | } 354 | 355 | return g_steal_pointer (&query); 356 | } 357 | 358 | static GPtrArray * 359 | get_packages_deps (DnfContext *ctx, GPtrArray *packages, GError **error) 360 | { 361 | DnfSack *sack = dnf_context_get_sack (ctx); 362 | 363 | g_autoptr(GPtrArray) deps = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); 364 | 365 | for (guint i = 0; i < packages->len; ++i) 366 | { 367 | DnfPackage * pkg = g_ptr_array_index (packages, i); 368 | HyGoal goal = hy_goal_create (sack); 369 | hy_goal_install (goal, pkg); 370 | if (hy_goal_run_flags (goal, DNF_NONE) == 0) 371 | { 372 | ptr_array_extend_and_steal (deps, hy_goal_list_installs (goal, NULL)); 373 | ptr_array_extend_and_steal (deps, hy_goal_list_upgrades (goal, NULL)); 374 | } 375 | else 376 | { 377 | g_set_error_literal (error, DNF_ERROR, DNF_ERROR_NO_SOLUTION, "Error in resolve of packages"); 378 | hy_goal_free (goal); 379 | return NULL; 380 | } 381 | hy_goal_free (goal); 382 | } 383 | 384 | return g_steal_pointer (&deps); 385 | } 386 | 387 | static gboolean 388 | dnf_command_download_run (DnfCommand *cmd, 389 | int argc, 390 | char *argv[], 391 | GOptionContext *opt_ctx, 392 | DnfContext *ctx, 393 | GError **error) 394 | { 395 | g_auto(GStrv) opt_key = NULL; 396 | g_autofree gchar *opt_archlist = NULL; 397 | gboolean opt_src = FALSE; 398 | gboolean opt_resolve = FALSE; 399 | gboolean opt_alldeps = FALSE; 400 | const GOptionEntry opts[] = { 401 | { "archlist", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &opt_archlist, "limit the query to packages of given architectures", "ARCH,..."}, 402 | { "resolve", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_resolve, "resolve and download needed dependencies", NULL }, 403 | { "alldeps", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_alldeps, "when running with --resolve, download all dependencies (do not exclude already installed ones)", NULL }, 404 | { "source", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_src, "download source packages", NULL }, 405 | { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &opt_key, NULL, NULL }, 406 | { NULL } 407 | }; 408 | g_option_context_add_main_entries (opt_ctx, opts, NULL); 409 | 410 | if (!g_option_context_parse (opt_ctx, &argc, &argv, error)) 411 | return FALSE; 412 | 413 | if (opt_key == NULL) 414 | { 415 | g_set_error_literal (error, 416 | G_IO_ERROR, 417 | G_IO_ERROR_FAILED, 418 | "Packages are not specified"); 419 | return FALSE; 420 | } 421 | 422 | DnfRepoLoader * repo_loader = dnf_context_get_repo_loader (ctx); 423 | // If -source arg was passed, auto-enable the source repositories 424 | if (opt_src && !dnf_command_download_enablesourcerepos (ctx, repo_loader, error)) 425 | { 426 | return FALSE; 427 | } 428 | 429 | DnfState * state = dnf_context_get_state (ctx); 430 | DnfContextSetupSackFlags sack_flags = !opt_resolve || opt_alldeps ? DNF_CONTEXT_SETUP_SACK_FLAG_SKIP_RPMDB 431 | : DNF_CONTEXT_SETUP_SACK_FLAG_NONE; 432 | if (!dnf_context_setup_sack_with_flags (ctx, state, sack_flags, error)) { 433 | return FALSE; 434 | } 435 | 436 | hy_autoquery HyQuery query = get_packages_query (ctx, opt_key, opt_src, opt_archlist); 437 | 438 | g_autoptr(GPtrArray) pkgs = hy_query_run (query); 439 | 440 | if (pkgs->len == 0) 441 | { 442 | g_print ("No packages matched.\n"); 443 | return FALSE; 444 | } 445 | 446 | if (opt_resolve) 447 | { 448 | GPtrArray *deps = get_packages_deps (ctx, pkgs, error); 449 | if (!deps) 450 | { 451 | return FALSE; 452 | } 453 | ptr_array_extend_and_steal (pkgs, deps); 454 | } 455 | 456 | if (!download_packages (repo_loader, pkgs, state, error)) 457 | { 458 | return FALSE; 459 | } 460 | 461 | g_print ("Complete.\n"); 462 | 463 | return TRUE; 464 | } 465 | 466 | static void 467 | dnf_command_download_class_init (DnfCommandDownloadClass *klass) 468 | { 469 | } 470 | 471 | static void 472 | dnf_command_download_iface_init (DnfCommandInterface *iface) 473 | { 474 | iface->run = dnf_command_download_run; 475 | } 476 | 477 | static void 478 | dnf_command_download_class_finalize (DnfCommandDownloadClass *klass) 479 | { 480 | } 481 | 482 | G_MODULE_EXPORT void 483 | dnf_command_download_register_types (PeasObjectModule *module) 484 | { 485 | dnf_command_download_register_type (G_TYPE_MODULE (module)); 486 | 487 | peas_object_module_register_extension_type (module, 488 | DNF_TYPE_COMMAND, 489 | DNF_TYPE_COMMAND_DOWNLOAD); 490 | } 491 | -------------------------------------------------------------------------------- /dnf/dnf-main.c: -------------------------------------------------------------------------------- 1 | /* dnf-main.c 2 | * 3 | * Copyright © 2010-2015 Richard Hughes 4 | * Copyright © 2016 Colin Walters 5 | * Copyright © 2016-2017 Igor Gnatenko 6 | * Copyright © 2017-2021 Jaroslav Rohel 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "dnf-command.h" 29 | #include "dnf-utils.h" 30 | 31 | typedef enum { ARG_DEFAULT, ARG_FALSE, ARG_TRUE } BoolArgs; 32 | 33 | static BoolArgs opt_install_weak_deps = ARG_DEFAULT; 34 | static BoolArgs opt_allow_vendor_change = ARG_DEFAULT; 35 | static BoolArgs opt_keepcache = ARG_DEFAULT; 36 | static gboolean opt_no = FALSE; 37 | static gboolean opt_yes = FALSE; 38 | static gboolean opt_nodocs = FALSE; 39 | static gboolean opt_best = FALSE; 40 | static gboolean opt_nobest = FALSE; 41 | static gboolean opt_test = FALSE; 42 | static gboolean opt_refresh = FALSE; 43 | static gboolean show_help = FALSE; 44 | static gboolean dl_pkgs_printed = FALSE; 45 | static GSList *enable_disable_repos = NULL; 46 | static gboolean disable_plugins_loading = FALSE; 47 | static gboolean config_used = FALSE; 48 | static gboolean enable_disable_plugin_used = FALSE; 49 | static gboolean installroot_used = FALSE; 50 | static gboolean cachedir_used = FALSE; 51 | static gboolean reposdir_used = FALSE; 52 | static gboolean varsdir_used = FALSE; 53 | 54 | static gboolean 55 | process_global_option (const gchar *option_name, 56 | const gchar *value, 57 | gpointer data, 58 | GError **error) 59 | { 60 | g_autoptr(GError) local_error = NULL; 61 | DnfContext *ctx = DNF_CONTEXT (data); 62 | 63 | gboolean ret = TRUE; 64 | if (g_strcmp0 (option_name, "--config") == 0) 65 | { 66 | config_used = TRUE; 67 | dnf_context_set_config_file_path (value); 68 | } 69 | else if (g_strcmp0 (option_name, "--disablerepo") == 0) 70 | { 71 | enable_disable_repos = g_slist_append (enable_disable_repos, g_strconcat("d", value, NULL)); 72 | } 73 | else if (g_strcmp0 (option_name, "--enablerepo") == 0) 74 | { 75 | enable_disable_repos = g_slist_append (enable_disable_repos, g_strconcat("e", value, NULL)); 76 | } 77 | else if (g_strcmp0 (option_name, "--disableplugin") == 0) 78 | { 79 | g_auto(GStrv) patterns = g_strsplit (value, ",", -1); 80 | for (char **it = patterns; *it; ++it) 81 | dnf_context_disable_plugins (*it); 82 | enable_disable_plugin_used = TRUE; 83 | } 84 | else if (g_strcmp0 (option_name, "--enableplugin") == 0) 85 | { 86 | g_auto(GStrv) patterns = g_strsplit (value, ",", -1); 87 | for (char **it = patterns; *it; ++it) 88 | dnf_context_enable_plugins (*it); 89 | enable_disable_plugin_used = TRUE; 90 | } 91 | else if (g_strcmp0 (option_name, "--installroot") == 0) 92 | { 93 | installroot_used = TRUE; 94 | if (value[0] != '/') 95 | { 96 | local_error = g_error_new (G_OPTION_ERROR, 97 | G_OPTION_ERROR_BAD_VALUE, 98 | "Absolute path must be used"); 99 | ret = FALSE; 100 | } 101 | else 102 | { 103 | dnf_context_set_install_root (ctx, value); 104 | } 105 | } 106 | else if (g_strcmp0 (option_name, "--releasever") == 0) 107 | { 108 | dnf_context_set_release_ver (ctx, value); 109 | } 110 | else if (g_strcmp0 (option_name, "--setopt") == 0) 111 | { 112 | g_auto(GStrv) setopt = g_strsplit (value, "=", 2); 113 | if (!setopt[0] || !setopt[1]) 114 | { 115 | local_error = g_error_new (G_OPTION_ERROR, 116 | G_OPTION_ERROR_BAD_VALUE, 117 | "Missing value in: %s", value); 118 | ret = FALSE; 119 | } 120 | else if (strchr (setopt[0], '.')) 121 | { /* repository option, pass to libdnf */ 122 | ret = dnf_conf_add_setopt (setopt[0], DNF_CONF_COMMANDLINE, setopt[1], &local_error); 123 | } 124 | else if (strcmp (setopt[0], "tsflags") == 0) 125 | { 126 | g_auto(GStrv) tsflags = g_strsplit (setopt[1], ",", -1); 127 | for (char **it = tsflags; *it; ++it) 128 | { 129 | if (strcmp (*it, "nodocs") == 0) 130 | opt_nodocs = TRUE; 131 | else if (strcmp (*it, "test") == 0) 132 | opt_test = TRUE; 133 | else 134 | { 135 | local_error = g_error_new (G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, 136 | "Unknown tsflag: %s", *it); 137 | ret = FALSE; 138 | break; 139 | } 140 | } 141 | } 142 | else if (strcmp (setopt[0], "module_platform_id") == 0) 143 | { 144 | const char *module_platform_id = setopt[1]; 145 | if (module_platform_id[0] != '\0') 146 | { 147 | dnf_context_set_platform_module (ctx, module_platform_id); 148 | } 149 | else 150 | { 151 | local_error = g_error_new (G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, 152 | "Empty value in: %s", value); 153 | ret = FALSE; 154 | } 155 | } 156 | else if (strcmp (setopt[0], "cachedir") == 0) 157 | { 158 | cachedir_used = TRUE; 159 | const char *cachedir = setopt[1]; 160 | if (cachedir[0] != '\0') 161 | { 162 | g_autofree gchar *metadatadir = g_build_path ("/", cachedir, "metadata", NULL); 163 | dnf_context_set_cache_dir (ctx, metadatadir); 164 | g_autofree gchar *solvdir = g_build_path ("/", cachedir, "solv", NULL); 165 | dnf_context_set_solv_dir (ctx, solvdir); 166 | g_autofree gchar *lockdir = g_build_path ("/", cachedir, "lock", NULL); 167 | dnf_context_set_lock_dir (ctx, lockdir); 168 | } 169 | else 170 | { 171 | local_error = g_error_new (G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, 172 | "Empty value in: %s", value); 173 | ret = FALSE; 174 | } 175 | } 176 | else if (strcmp (setopt[0], "install_weak_deps") == 0) 177 | { 178 | const char *setopt_val = setopt[1]; 179 | if (setopt_val[0] == '1' && setopt_val[1] == '\0') 180 | opt_install_weak_deps = ARG_TRUE; 181 | else if (setopt_val[0] == '0' && setopt_val[1] == '\0') 182 | opt_install_weak_deps = ARG_FALSE; 183 | else 184 | { 185 | local_error = g_error_new (G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, 186 | "Invalid boolean value \"%s\" in: %s", setopt[1], value); 187 | ret = FALSE; 188 | } 189 | } 190 | else if (strcmp (setopt[0], "allow_vendor_change") == 0) 191 | { 192 | const char *setopt_val = setopt[1]; 193 | if (setopt_val[0] == '1' && setopt_val[1] == '\0') 194 | opt_allow_vendor_change = ARG_TRUE; 195 | else if (setopt_val[0] == '0' && setopt_val[1] == '\0') 196 | opt_allow_vendor_change = ARG_FALSE; 197 | else 198 | { 199 | local_error = g_error_new (G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, 200 | "Invalid boolean value \"%s\" in: %s", setopt[1], value); 201 | ret = FALSE; 202 | } 203 | } 204 | else if (strcmp (setopt[0], "keepcache") == 0) 205 | { 206 | const char *setopt_val = setopt[1]; 207 | if (setopt_val[0] == '1' && setopt_val[1] == '\0') 208 | opt_keepcache = ARG_TRUE; 209 | else if (setopt_val[0] == '0' && setopt_val[1] == '\0') 210 | opt_keepcache = ARG_FALSE; 211 | else 212 | { 213 | local_error = g_error_new (G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, 214 | "Invalid boolean value \"%s\" in: %s", setopt[1], value); 215 | ret = FALSE; 216 | } 217 | } 218 | else if (strcmp (setopt[0], "reposdir") == 0) 219 | { 220 | reposdir_used = TRUE; 221 | g_auto(GStrv) reposdir = g_strsplit (setopt[1], ",", -1); 222 | dnf_context_set_repos_dir (ctx, (const gchar * const *)reposdir); 223 | } 224 | else if (strcmp (setopt[0], "varsdir") == 0) 225 | { 226 | varsdir_used = TRUE; 227 | g_auto(GStrv) varsdir = g_strsplit (setopt[1], ",", -1); 228 | dnf_context_set_vars_dir (ctx, (const gchar * const *)varsdir); 229 | } 230 | else 231 | { 232 | local_error = g_error_new (G_OPTION_ERROR, 233 | G_OPTION_ERROR_BAD_VALUE, 234 | "Unable to handle: %s", value); 235 | ret = FALSE; 236 | } 237 | } 238 | else 239 | g_assert_not_reached (); 240 | 241 | if (local_error != NULL) 242 | g_set_error (error, 243 | G_OPTION_ERROR, 244 | G_OPTION_ERROR_BAD_VALUE, 245 | "(%s) %s", option_name, local_error->message); 246 | 247 | return ret; 248 | } 249 | 250 | static const GOptionEntry global_opts[] = { 251 | { "assumeno", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_no, "Automatically answer no for all questions", NULL }, 252 | { "assumeyes", 'y', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_yes, "Automatically answer yes for all questions", NULL }, 253 | { "best", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_best, "Try the best available package versions in transactions", NULL }, 254 | { "config", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, "Configuration file location", "" }, 255 | { "disablerepo", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, "Disable repository by an id", "ID" }, 256 | { "disableplugin", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, "Disable plugins by name", "name" }, 257 | { "enablerepo", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, "Enable repository by an id", "ID" }, 258 | { "enableplugin", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, "Enable plugins by name", "name" }, 259 | { "nobest", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_nobest, "Do not limit the transaction to the best candidates", NULL }, 260 | { "installroot", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, "Set install root", "PATH" }, 261 | { "nodocs", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_nodocs, "Install packages without docs", NULL }, 262 | { "noplugins", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &disable_plugins_loading, "Disable loading of plugins", NULL }, 263 | { "refresh", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_refresh, "Set metadata as expired before running the command", NULL }, 264 | { "releasever", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, "Override the value of $releasever in config and repo files", "RELEASEVER" }, 265 | { "setopt", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, process_global_option, 266 | "Override a configuration option (install_weak_deps=0/1, allow_vendor_change=0/1, keepcache=0/1, module_platform_id=, cachedir=, reposdir=,,..., tsflags=nodocs/test, varsdir=,,..., repo_id.option_name=)", "