Skip to content

dnf5 copr plugin: Allow a vendor change for enabled Copr repositories - #3004

Open
jrohel wants to merge 4 commits into
rpm-software-management:mainfrom
jrohel:copr-plugin-vendor-policy-support
Open

jrohel wants to merge 4 commits into
rpm-software-management:mainfrom
jrohel:copr-plugin-vendor-policy-support

Conversation

@jrohel

@jrohel jrohel commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Resolves: #3003

The enable command now asks whether packages from the Copr repositories it just enabled (the main one, plus any enabled multilib/dependency repositories) should be allowed to cross a vendor boundary during package replacement (upgrade/downgrade/reinstall), and saves the answer as vendor change policies.

  • Interactive prompt with 4 choices:

    • no vendor change,
    • allow packages from these repositories to replace an already-installed package from another vendor (to-repo),
    • allow a package installed from these repositories to be replaced by another vendor (from-repo),
    • or both.
  • The default is configurable, via a vendor_change key in the [main] section of the Copr configuration, using the same four values as new --vendor-change= option. This default is used directly with --assumeyes, or as the interactive prompt's default otherwise; it falls back to false if not set.

  • --assumeyes skips the prompt and keeps the default without asking.

  • New --vendor-change=to-repo|from-repo|true|false option sets the choice directly, bypassing both the interactive prompt and the --assumeyes default. Any OptionBool-recognized value works in place of true/false.

Allowing both directions requires two separate policy files. The two files are distinguished by an "i"/"o" prefix on the base filename.

The disable command resets both policies to empty, since disabling a Copr repository disables all of its repo parts and the policies would have no effect anyway.

The remove command removes both policy files entirely, skipping ones that don't exist or are distribution-provided (not manageable).

All three commands derive the policies' base filename from the repo configuration filename, plus the "i"/"o" prefix and minus the ".repo" extension, so a policy can always be matched back to its Copr repository.

Example outputs:

# dnf copr enable praiskup/test-deps
 https://copr.fedorainfracloud.org/api_3/rpmrepo/praiskup/test-deps/fedora-rawhide/                                                                                                                                   100% |   2.8 KiB/s |   1.1 KiB |  00m00s
Enabling a Copr repository. Please note that this repository is not part
of the main distribution, and quality may vary.

The Fedora Project does not exercise any power over the contents of
this repository beyond the rules outlined in the Copr FAQ at
<https://docs.copr.fedorainfracloud.org/user_documentation.html#what-i-can-build-in-copr>,
and packages are not held to any quality or security level.

Please do not file bug reports about these packages in Fedora
Bugzilla. In case of problems, contact the owner of this repository.
Is this ok [y/N]: y

Maintainer of the enabled Copr repository decided to make
it dependent on other repositories. Such repositories are
usually necessary for successful installation of RPMs from
the main Copr repository (they provide runtime dependencies).

Be aware that the note about quality and bug-reporting
above applies here too, Fedora Project doesn't control the
content. Please review the list:

  1. [coprdep:copr.fedorainfracloud.org:group_copr:copr]
     baseurl=https://download.copr.fedorainfracloud.org/results/@copr/copr/fedora-$releasever-$basearch/

  2. [coprdep:https_example_com_foo_bar_repo]
     baseurl=https://example.com/foo/bar/repo/

These repositories are being enabled together with the main
repository.

Is this ok [y/N]: y

Packages from the repositories enabled by this command can be allowed to
replace, or be replaced by, packages from a different vendor during package
replacement (upgrade/downgrade/reinstall) operations:
  1. Do not allow a vendor change in either direction
  2. Allow packages from the repositories enabled by this command to
     replace an already installed package from a different vendor
  3. Allow a package installed from the repositories enabled by this
     command to be replaced by a package from a different vendor
  4. Allow both of the above (vendor change allowed in both directions)
Enter your choice [1-4, default 1]: 4
Saved vendor policy file: /etc/dnf/vendors.d/i_copr:copr.fedorainfracloud.org:praiskup:test-deps.conf
Saved vendor policy file: /etc/dnf/vendors.d/o_copr:copr.fedorainfracloud.org:praiskup:test-deps.conf
# dnf copr disable praiskup/test-deps
Copr repository 'copr.fedorainfracloud.org/praiskup/test-deps' in '/etc/yum.repos.d/_copr:copr.fedorainfracloud.org:praiskup:test-deps.repo' disabled.
Vendor policy file updated: /etc/dnf/vendors.d/i_copr:copr.fedorainfracloud.org:praiskup:test-deps.conf
Vendor policy file updated: /etc/dnf/vendors.d/o_copr:copr.fedorainfracloud.org:praiskup:test-deps.conf
# dnf copr remove praiskup/test-deps
Repo file /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:praiskup:test-deps.repo successfully removed
Removed vendor policy file: /etc/dnf/vendors.d/i_copr:copr.fedorainfracloud.org:praiskup:test-deps.conf
Removed vendor policy file: /etc/dnf/vendors.d/o_copr:copr.fedorainfracloud.org:praiskup:test-deps.conf

CI tests are included

@jrohel
jrohel requested a review from a team as a code owner October 23, 2026 14:30
@jrohel
jrohel requested review from ppisar and removed request for a team October 23, 2026 14:30
@jrohel
jrohel marked this pull request as draft October 23, 2026 14:31
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

PR Summary by Qodo

Manage vendor-change policies for Copr repositories

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes


AI Description

• Let Copr users choose vendor-change permissions interactively or with --vendor-change,
 defaulting to neither direction.
• Apply separate policies to enabled Copr repository parts; reset them on disable and remove them on
 removal.
• Create missing vendor-policy directories for minimal installroots and cover command output in
 integration tests.
Diagram

graph TD
  E["Copr enable"] --> R{"Repo saved?"} -->|yes| P["Enabled repo IDs"] --> C{"Vendor choice"} --> M["Vendor manager"] --> F["Directional policies"]
  D["Disable or remove"] -->|reset or delete| M
Loading
High-Level Assessment

The approach fits the existing VendorChangeManager API. Separate incoming and outgoing policies are necessary because filters within one policy are combined, while deriving filenames from the Copr repo file keeps lifecycle operations aligned. Reusing the manager for directory creation and file operations is preferable to duplicating filesystem handling in the plugin.

Files changed (8) +444 / -13

Enhancement (6) +331 / -13
copr.hppStore the optional enable-command vendor choice +6/-0

Store the optional enable-command vendor choice

• Adds state for an explicit '--vendor-change' choice, distinct from an interactive selection or the '--assumeyes' default.

dnf5-plugins/copr_plugin/copr.hpp

copr_enable.cppSelect and save directional policies when enabling Copr +187/-1

Select and save directional policies when enabling Copr

• Adds the command option and four-choice prompt, then saves separate incoming and outgoing policies for enabled repository IDs. Policy selection runs only after the repository is saved; save failures produce warnings.

dnf5-plugins/copr_plugin/copr_enable.cpp

copr_repo.cppTie policy filenames and cleanup to the Copr lifecycle +92/-10

Tie policy filenames and cleanup to the Copr lifecycle

• Derives a shared filename base from the Copr ID and exposes enabled repository IDs. Disabling resets both policies; removing deletes existing manageable policy files while leaving distribution-provided files alone.

dnf5-plugins/copr_plugin/copr_repo.cpp

copr_repo.hppExpose saved-state and repository-policy metadata +14/-2

Expose saved-state and repository-policy metadata

• Declares accessors for the policy filename base and enabled repo IDs. Makes 'save_interactive()' report whether it saved the repo, and makes the repo-part enabled accessor const.

dnf5-plugins/copr_plugin/copr_repo.hpp

vendor_change_manager.hppDeclare vendor configuration directory creation API +8/-0

Declare vendor configuration directory creation API

• Adds a documented method to ensure the vendor-policy directory and its parents exist before saving policies, including under an installroot.

include/libdnf5/base/vendor_change_manager.hpp

vendor_change_manager.cppCreate missing vendor-policy directories +24/-0

Create missing vendor-policy directories

• Implements directory creation using the manager's existing installroot-aware path and raises a VendorChangeManagerError if creation fails.

libdnf5/base/vendor_change_manager.cpp

Tests (2) +113 / -0
copr-chroot.featureExpect policy creation for chroot-based Copr enablement +4/-0

Expect policy creation for chroot-based Copr enablement

• Extends the existing scenario's expected output with the '--assumeyes' default and both saved policy paths.

integration-tests/dnf-behave-tests/dnf/plugins-core/copr-chroot.feature

copr.featureCover vendor-change options and lifecycle output +109/-0

Cover vendor-change options and lifecycle output

• Adds output scenarios for 'to-repo', 'from-repo', 'true', and 'false'. Updates enable and disable expectations for default policy creation and reset.

integration-tests/dnf-behave-tests/dnf/plugins-core/copr.feature

Comment on lines 463 to +464
save();
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Remediation Recommended

2. Failed repo writes still create policies 🐞 Bug ≡ Correctness

save_interactive() returns true after save() without checking whether the repo-file stream
opened or completed its writes. If an existing repo file cannot be opened for writing but its
permissions can still be changed, the new caller proceeds to create a policy for the in-memory
enabled repositories even though the requested repo configuration was not saved.
Agent Prompt
## Issue description
A failed repo-file write can be reported as a successful save, triggering vendor-policy creation.

## Fix Focus Areas
- dnf5-plugins/copr_plugin/copr_repo.cpp[377-396]
- dnf5-plugins/copr_plugin/copr_repo.cpp[461-464]

## Recommended Fix
Check the output stream after opening, writing, and closing the repo file, and propagate any failure instead of returning true. Only invoke policy creation after a verified save.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a new commit: save() now uses libdnf5::utils::fs::File, which throws libdnf5::FileSystemError on failure.

Comment thread dnf5-plugins/copr_plugin/copr_repo.cpp Resolved

choice = 1;
while (true) {
std::cerr << _("Enter your choice [1-4, default 1]: ");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have libdnf5::Message for a dialogue with a user?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't thought about that yet. This is a plugin for the dnf5 application, not for the libdnf5 library. So for now, I'm sticking to the console output style already used in the plugin, and I'll see how things go in the future.

@jrohel
jrohel force-pushed the copr-plugin-vendor-policy-support branch 2 times, most recently from c63afed to 9947690 Compare October 26, 2026 08:58
@jrohel
jrohel marked this pull request as ready for review October 26, 2026 09:14
Comment thread dnf5-plugins/copr_plugin/copr_repo.cpp Resolved
Comment thread dnf5-plugins/copr_plugin/copr_repo.cpp Resolved
The 'enable' command now asks whether a vendor change to/from packages
of the repositories it just enabled (the main one, plus any enabled
multilib/dependency repositories) should be allowed, and writes the
answer as vendor change policies. The default is to not allow it in
either direction; with --assumeyes, this default is used without asking.

Allowing both directions requires two separate policy files. The two
files are distinguished by an "i"/"o" prefix on the base filename.

The 'disable' command resets both policies to empty, since disabling
a Copr repository disables all of its repo parts and the policies
would have no effect anyway.

The 'remove' command removes both policy files entirely, skipping
ones that don't exist or are distribution-provided (not manageable).

All three commands derive the policies' base filename from the repo
configuration filename, plus the "i"/"o" prefix and minus the ".repo"
extension, so a policy can always be matched back to its Copr
repository.

CI test updated
@jrohel
jrohel force-pushed the copr-plugin-vendor-policy-support branch from 259f8a8 to f6138a7 Compare October 27, 2026 19:53
The new "--vendor-change=to-repo|from-repo|true|false" option sets the
vendor change choice directly instead of asking interactively or
using the configured/--assumeyes default.

- "to-repo" allows packages from the repositories enabled by this
  command to replace an already installed package from a different
  vendor,
- "from-repo" allows a package installed from these repositories to be
  replaced by a package from a different vendor,
- "true" allows both
- "false" allows neither.

Any OptionBool-recognized value can be used in place of "true"/"false".

The choice is also configurable as a default, via a "vendor_change"
key in the "[main]" section of the Copr configuration, using the same
four values. This default is used directly with --assumeyes, or as the
interactive prompt's default otherwise; it falls back to "false" if
not set.

Bump copr plugin version to 0.2.0.
CoprRepo::save() wrote the .repo file via a plain std::ofstream, which
does not throw on error unless exceptions() is explicitly enabled --
a failure to open or write the file (e.g. when a directory with the same
name exists) would be silently ignored instead of being reported.

Use libdnf5::utils::fs::File instead, which raises
libdnf5::FileSystemError on filesystem errors.
@jrohel
jrohel force-pushed the copr-plugin-vendor-policy-support branch from f6138a7 to a051e2b Compare October 29, 2026 11:30
@praiskup

Copy link
Copy Markdown
Member

Sorry that I can not provide a formal review (time constraints), but I like the UI (the question regarding Vendors is very tough, so users will be confused for sure -- but I fail to find better or easier wording).

For dnf copr enable foo/bar -y though, we should either allow vendor changing entirely, or at least use to-repo (because most of the users out there doing -y want to start installing the stuff from the freshly enabled repository no matter what, e.g., inside Containerfiles)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RFE] Add vendor change policy support to dnf5 copr plugin

3 participants