Skip to content

Etc merge changes#2301

Open
Johan-Liebert1 wants to merge 3 commits into
bootc-dev:mainfrom
Johan-Liebert1:etc-merge-changes
Open

Etc merge changes#2301
Johan-Liebert1 wants to merge 3 commits into
bootc-dev:mainfrom
Johan-Liebert1:etc-merge-changes

Conversation

@Johan-Liebert1

Copy link
Copy Markdown
Collaborator

etc-merge: Handle unmergable paths properly

We would have unmergable paths if a modified file was changed to a
directory in the new etc or vice-versa. One of the major issues was that
we were erroring out during "merge" which is not ideal. A new vector now
keeps track of all unmergable paths and the reason they're not mergable.

Ref: composefs/composefs-rs/issues/335


cfs/stage: Compute etc diff before staging

Before we write the staged deployment file at /run/composefs and
before we create new boot entries, we now compute the etc diff in
advance to check whethere we will face any merge conflicts while
finalizing the deployment. If we find conflicts we exit with and error
and detailing where conflicts were found


tmt: Add tests for etc merge conflict

This was predominantly AI generated with some minor tweaks from me.

Makes sure that bootc upgrade/switch fails if merge conflicts are found
during three way etc merge.

@Johan-Liebert1 Johan-Liebert1 requested a review from cgwalters July 9, 2026 09:37
@Johan-Liebert1 Johan-Liebert1 added the ci/tier-1 Run CI for tier-1 OS (centos-10) only label Jul 9, 2026
@bootc-bot bootc-bot Bot requested a review from gursewak1997 July 9, 2026 09:39
We would have unmergable paths if a modified file was changed to a
directory in the new etc or vice-versa. One of the major issues was that
we were erroring out during "merge" which is not ideal. A new vector now
keeps track of all unmergable paths and the reason they're not mergable.

Ref: composefs/composefs-rs/issues/335

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Before we write the staged deployment file at `/run/composefs` and
before we create new boot entries, we now compute the etc diff in
advance to check whethere we will face any merge conflicts while
finalizing the deployment. If we find conflicts we exit with and error
and detailing where conflicts were found

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
This was predominantly AI generated with some minor tweaks from me.

Makes sure that bootc upgrade/switch fails if merge conflicts are found
during three way etc merge.

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
current: &Directory<CustomMetadata>,
pristine_leaves: &[Leaf<CustomMetadata>],
current_leaves: &[Leaf<CustomMetadata>],
new_leaves: &[Leaf<CustomMetadata>],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is unused, the only "usage" is to pass it via recursion below. AI spotted this but I'm surprised the compiler doesn't catch it.

Edit: actually clippy does catch it!

warning: parameter is only used in recursion
   --> crates/etc-merge/src/lib.rs:242:5
    |
242 |     new_leaves: &[Leaf<CustomMetadata>],
    |     ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_new_leaves`
    |
note: parameter used here
   --> crates/etc-merge/src/lib.rs:269:29
    |
269 | ...                   new_leaves,
    |                       ^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#only_used_in_recursion
    = note: `#[warn(clippy::only_used_in_recursion)]` on by default

Ok(())
}

fn check_if_mergable(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This should probably return Result since below it calls get_directory which can fail, and currently it's just swallowing any unexpected Err but it should probably re-raise instead?

if diff.added.len() != total_added {
diff.added.insert(total_added, current_path.clone());
} else if diff.modified.len() != total_modified {
diff.modified.insert(total_added, current_path.clone());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should total_added here be total_modified instead? That's how it was in the old version and I think it should still be the case here

fn check_if_mergable(
new: &Directory<CustomMetadata>,
current_inode: &Inode<CustomMetadata>,
current_path: &PathBuf,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should just be &Path per clippy

warning: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
   --> crates/etc-merge/src/lib.rs:184:19
    |
184 |     current_path: &PathBuf,
    |                   ^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#ptr_arg
    = note: `#[warn(clippy::ptr_arg)]` on by default
help: change this to
    |
184 ~     current_path: &Path,
185 |     diff: &mut Diff,
...
194 |                 diff.unmergable_paths.push(UnmergablePaths {
195 ~                     path: current_path.to_path_buf(),
196 |                     reason: format!(
...
210 |                 diff.unmergable_paths.push(UnmergablePaths {
211 ~                     path: current_path.to_path_buf(),
    |

)?;

print_diff(&diff, &mut std::io::stdout());
if print {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This logic should probably just go in the caller? As far as I can tell, this function is only called in two places, and only the one in cli.rs passes print: true

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

Labels

ci/tier-1 Run CI for tier-1 OS (centos-10) only

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants