systemd / mkosi

💽 Build Bespoke OS Images
https://mkosi.systemd.io/
1.18k stars 319 forks source link

Copying in trees from build script fails with overwriting symlinks #2168

Closed Cornelicorn closed 8 months ago

Cornelicorn commented 11 months ago

This is the same issue as https://github.com/systemd/mkosi/issues/166 but as it reappeared, I thought I'd open a new bug report.

I'm trying to build sbctl in an mkosi container. The output provides /usr/local/share/man/man8/sbctl.8, which is outputted into DESTDIR in mkosi.build.chroot in my case. mkosi then tries to install that file to the regular tree, which fails:

+ tree /work/dest
/work/dest
├── local_scratch
│   └── aur_packages
│       ├── pacman-hook-kernel-install.pkg.tar.zst
│       └── paru.pkg.tar.zst
└── usr
    └── local
        ├── bin
        │   └── sbctl
        ├── lib
        │   └── kernel
        │       └── install.d
        │           └── 91-sbctl.install
        └── share
            ├── bash-completion
            │   └── completions
            │       └── sbctl
            ├── fish
            │   └── vendor_completions.d
            │       └── sbctl.fish
            ├── licenses
            │   └── sbctl
            │       └── LICENSE
            ├── man
            │   └── man8
            │       └── sbctl.8
            └── zsh
                └── site-functions
                    └── _sbctl

20 directories, 9 files
+ tree //usr/local
//usr/local
├── bin
├── etc
├── games
├── include
├── lib
├── man
├── sbin
├── share
│   └── man -> ../man
└── src

11 directories, 0 files
‣  Copying in build tree…
cp: cannot overwrite non-directory '/home/cnhof/.cache/mkosi-workspace62czz5gn/root/usr/local/share/man' with directory '/home/cnhof/.cache/mkosi-workspace62czz5gn/dest/usr/local/share/man'
‣ "cp --recursive --no-dereference --preserve=mode,timestamps,links,xattr,ownership --reflink=auto /home/cnhof/.cache/mkosi-workspace62czz5gn/dest /home/cnhof/.cache/mkosi-workspace62czz5gn/root --no-target-directory" returned non-zero exit code 1.
DaanDeMeyer commented 11 months ago

Yes this is a known issue. Unfortunately cp just can't handle this. And rsync doesn't support reflinks, so whatever we use will be bad in some form.

Ideally someone would implement --keep-directory-symlink for cp.

DaanDeMeyer commented 11 months ago

Ideally someone would implement --keep-directory-symlink for cp.

Just submitted a patch, will link it here once it appears in the archives. This won't fix your issue but it will at least provide a future solution if accepted.

DaanDeMeyer commented 11 months ago

https://lists.gnu.org/archive/html/bug-coreutils/2023-12/msg00022.html

Cornelicorn commented 11 months ago

Just to confirm: This works for me, when using an extra search path for cp and

diff --git a/mkosi/tree.py b/mkosi/tree.py
index 014f130..27d3ef1 100644
--- a/mkosi/tree.py
+++ b/mkosi/tree.py
@@ -68,6 +68,8 @@ def copy_tree(
         "--no-dereference",
         f"--preserve=mode,timestamps,links,xattr{',ownership' if preserve_owner else ''}",
         "--reflink=auto",
+        "--copy-contents",
+        "--keep-directory-symlink",
         src, dst,
     ]