genpac 0.1.0

Sandbox for Gentoo ebuild development using bubblewrap
// Copyright (C) 2023 Gokul Das B
// SPDX-License-Identifier: GPL-3.0-or-later
//! New headers
//!
//! This module deals with creation of new GNU tar header for the destination archive.

use super::ArchiveEntity;
use crate::GlobalsFinal;
use anyhow::Result as AResult;
use std::path::Path;
use tar::Header;

pub(super) enum NewHeader<'a, 'b> {
    Primary {
        header: Header,
        path: &'a Path,
    },
    Link {
        header: Header,
        path: &'a Path,
        target: &'b Path,
    },
}

impl<'a> NewHeader<'a, 'a> {
    pub(super) fn create(entity: &'a ArchiveEntity, globals: &GlobalsFinal) -> AResult<Self> {
        let mut header = Header::new_gnu();

        // Map UID and GID to final value
        let uid = globals.remap_uid(entity.header.uid()?)?;
        header.set_uid(uid);
        let gid = globals.remap_gid(entity.header.gid()?)?;
        header.set_gid(gid);

        header.set_size(entity.header.size()?);
        header.set_mtime(entity.meta.mtime);
        header.set_entry_type(entity.header.entry_type());
        header.set_mode(entity.header.mode()?);

        {
            let header = header
                .as_gnu_mut()
                .ok_or(anyhow::anyhow!("Failed to convert header type"))?;

            if let Some(atime) = entity.meta.atime {
                header.set_atime(atime);
            }

            if let Some(ctime) = entity.meta.ctime {
                header.set_ctime(ctime);
            }

            match entity.header.device_major() {
                Ok(Some(x)) => header.set_device_major(x),
                Err(_) => log::trace!("Decode error: Device major"),
                _ => (),
            }

            match entity.header.device_minor() {
                Ok(Some(x)) => header.set_device_minor(x),
                Err(_) => log::trace!("Decode error: Device minor"),
                _ => (),
            }

            if let Some(x) = entity.header.username()? {
                header.set_username(x)?;
            }

            if let Some(x) = entity.header.groupname()? {
                header.set_groupname(x)?;
            }
        }

        let path = entity.path();
        let result = if entity.is_link() {
            let target = entity.target().unwrap();
            Self::Link {
                header,
                path,
                target,
            }
        } else {
            Self::Primary { header, path }
        };
        Ok(result)
    }
}