partially implemented separate manifest management
parent
2623bcf2b3
commit
7ac80d12f3
|
@ -21,6 +21,7 @@ add_library(build MODULE
|
|||
src/commands.cpp
|
||||
src/package_staging.cpp
|
||||
src/checksums.cpp
|
||||
src/metadata.cpp
|
||||
)
|
||||
|
||||
# Set output properties
|
||||
|
@ -48,6 +49,7 @@ add_executable(build_standalone
|
|||
src/commands.cpp
|
||||
src/package_staging.cpp
|
||||
src/checksums.cpp
|
||||
src/metadata.cpp
|
||||
)
|
||||
|
||||
# Define the BUILD_STANDALONE macro for the standalone build
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* @file metadata.hpp
|
||||
* @brief Functions for handling DPM package stage metadata
|
||||
*
|
||||
* Defines functions for creating and manipulating metadata for DPM package stages.
|
||||
*
|
||||
* @copyright Copyright (c) 2025 SILO GROUP LLC
|
||||
* @author Chris Punches <chris.punches@silogroup.org>
|
||||
*
|
||||
* Part of the Dark Horse Linux Package Manager (DPM)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <dpmdk/include/CommonModuleAPI.hpp>
|
||||
#include "checksums.hpp"
|
||||
|
||||
/**
|
||||
* @brief Updates the contents manifest file for a package stage
|
||||
*
|
||||
* Creates the CONTENTS_MANIFEST_DIGEST file by scanning the contents directory
|
||||
* and generating a line for each file with control designation,
|
||||
* checksum, permissions, ownership, and path information.
|
||||
*
|
||||
* @param package_dir Root directory of the package stage
|
||||
* @return true if contents manifest generation was successful, false otherwise
|
||||
*/
|
||||
bool update_contents_manifest(const std::filesystem::path& package_dir);
|
||||
|
||||
/**
|
||||
* @brief Generates basic metadata files for a package stage
|
||||
*
|
||||
* Creates the necessary metadata files for a package stage with the provided information.
|
||||
* Does not generate the CONTENTS_MANIFEST_DIGEST which requires a separate call
|
||||
* to update_contents_manifest().
|
||||
*
|
||||
* @param package_dir Root directory of the package stage
|
||||
* @param package_name Name of the package
|
||||
* @param package_version Version of the package
|
||||
* @param architecture Architecture of the package (e.g., x86_64, aarch64)
|
||||
* @return true if metadata generation was successful, false otherwise
|
||||
*/
|
||||
bool metadata_generate_new(
|
||||
const std::filesystem::path& package_dir,
|
||||
const std::string& package_name,
|
||||
const std::string& package_version,
|
||||
const std::string& architecture
|
||||
);
|
|
@ -20,6 +20,7 @@
|
|||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include "checksums.hpp"
|
||||
#include "metadata.hpp"
|
||||
|
||||
/**
|
||||
* @brief Stages a DPM package
|
||||
|
|
|
@ -5,18 +5,35 @@ static int refresh_package_manifest(const std::string& stage_dir, bool force) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int generate_package_manifest(const std::string& stage_dir, bool force) {
|
||||
dpm_log(LOG_INFO, ("Generating package manifest for: " + stage_dir).c_str());
|
||||
static int generate_package_manifest(
|
||||
const std::string& package_dir,
|
||||
const std::string& package_name,
|
||||
const std::string& package_version,
|
||||
const std::string& architecture,
|
||||
bool force
|
||||
) {
|
||||
dpm_log(LOG_INFO, ("Generating package manifest for: " + package_dir).c_str());
|
||||
|
||||
// Generate the metadata files using the provided information
|
||||
if (!metadata_generate_new(std::filesystem::path(package_dir), package_name, package_version, architecture)) {
|
||||
dpm_log(LOG_ERROR, "Failed to generate metadata.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dpm_log(LOG_INFO, "Package content manifest generated successfully.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_manifest(int argc, char** argv) {
|
||||
// Parse command line options
|
||||
bool force = false;
|
||||
bool refresh_only = false;
|
||||
bool replace = false;
|
||||
bool verbose = false;
|
||||
bool show_help = false;
|
||||
std::string stage_dir = "";
|
||||
std::string package_dir = "";
|
||||
std::string package_name = "";
|
||||
std::string package_version = "";
|
||||
std::string architecture = "";
|
||||
|
||||
// Process command-line arguments
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
@ -24,14 +41,23 @@ int cmd_manifest(int argc, char** argv) {
|
|||
|
||||
if (arg == "-f" || arg == "--force") {
|
||||
force = true;
|
||||
} else if (arg == "-r" || arg == "--refresh-only") {
|
||||
refresh_only = true;
|
||||
} else if (arg == "-r" || arg == "--replace") {
|
||||
replace = true;
|
||||
} else if (arg == "-v" || arg == "--verbose") {
|
||||
verbose = true;
|
||||
} else if (arg == "-h" || arg == "--help" || "help" ) {
|
||||
} else if (arg == "-h" || arg == "--help" || arg == "help") {
|
||||
show_help = true;
|
||||
} else if ((arg == "-s" || arg == "--stage") && i + 1 < argc) {
|
||||
stage_dir = argv[i + 1];
|
||||
} else if ((arg == "-p" || arg == "--package-dir") && i + 1 < argc) {
|
||||
package_dir = argv[i + 1];
|
||||
i++; // Skip the next argument
|
||||
} else if ((arg == "-n" || arg == "--name") && i + 1 < argc) {
|
||||
package_name = argv[i + 1];
|
||||
i++; // Skip the next argument
|
||||
} else if ((arg == "-V" || arg == "--version") && i + 1 < argc) {
|
||||
package_version = argv[i + 1];
|
||||
i++; // Skip the next argument
|
||||
} else if ((arg == "-a" || arg == "--architecture") && i + 1 < argc) {
|
||||
architecture = argv[i + 1];
|
||||
i++; // Skip the next argument
|
||||
}
|
||||
}
|
||||
|
@ -41,18 +67,18 @@ int cmd_manifest(int argc, char** argv) {
|
|||
return cmd_manifest_help(argc, argv);
|
||||
}
|
||||
|
||||
// Validate that stage directory is provided
|
||||
if (stage_dir.empty()) {
|
||||
dpm_log(LOG_ERROR, "Stage directory is required (--stage/-s)");
|
||||
// Validate that package directory is provided
|
||||
if (package_dir.empty()) {
|
||||
dpm_log(LOG_ERROR, "Package directory is required (--package-dir/-p)");
|
||||
return cmd_manifest_help(argc, argv);
|
||||
}
|
||||
|
||||
// Expand path if needed
|
||||
stage_dir = expand_path(stage_dir);
|
||||
package_dir = expand_path(package_dir);
|
||||
|
||||
// Check if stage directory exists
|
||||
if (!std::filesystem::exists(stage_dir)) {
|
||||
dpm_log(LOG_ERROR, ("Stage directory does not exist: " + stage_dir).c_str());
|
||||
// Check if package directory exists
|
||||
if (!std::filesystem::exists(package_dir)) {
|
||||
dpm_log(LOG_ERROR, ("Package directory does not exist: " + package_dir).c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -62,10 +88,16 @@ int cmd_manifest(int argc, char** argv) {
|
|||
}
|
||||
|
||||
// Log the operation being performed
|
||||
if (refresh_only) {
|
||||
return refresh_package_manifest(stage_dir, force);
|
||||
if (replace) {
|
||||
// When replacing a manifest, we need name, version, and architecture
|
||||
if (package_name.empty() || package_version.empty() || architecture.empty()) {
|
||||
dpm_log(LOG_ERROR, "Package name, version, and architecture are required for replacing a manifest");
|
||||
return cmd_manifest_help(argc, argv);
|
||||
}
|
||||
|
||||
return generate_package_manifest(package_dir, package_name, package_version, architecture, force);
|
||||
} else {
|
||||
return generate_package_manifest(stage_dir, force);
|
||||
return refresh_package_manifest(package_dir, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,6 +200,23 @@ int cmd_unknown(const char* command, int argc, char** argv) {
|
|||
}
|
||||
|
||||
|
||||
int cmd_manifest_help(int argc, char** argv) {
|
||||
dpm_log(LOG_INFO, "Usage: dpm build manifest [options]");
|
||||
dpm_log(LOG_INFO, "");
|
||||
dpm_log(LOG_INFO, "Options:");
|
||||
dpm_log(LOG_INFO, " -p, --package-dir DIR Package directory path (required)");
|
||||
dpm_log(LOG_INFO, " -n, --name NAME Package name (required when replacing)");
|
||||
dpm_log(LOG_INFO, " -V, --version VERSION Package version (required when replacing)");
|
||||
dpm_log(LOG_INFO, " -a, --architecture ARCH Package architecture (required when replacing)");
|
||||
dpm_log(LOG_INFO, " -r, --replace Replace manifest with new one (default: refresh existing)");
|
||||
dpm_log(LOG_INFO, " -f, --force Force manifest operation even if warnings occur");
|
||||
dpm_log(LOG_INFO, " -v, --verbose Enable verbose output");
|
||||
dpm_log(LOG_INFO, " -h, --help Display this help message");
|
||||
dpm_log(LOG_INFO, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cmd_stage_help(int argc, char** argv) {
|
||||
dpm_log(LOG_INFO, "Usage: dpm build stage [options]");
|
||||
dpm_log(LOG_INFO, "");
|
||||
|
@ -184,16 +233,3 @@ int cmd_stage_help(int argc, char** argv) {
|
|||
dpm_log(LOG_INFO, " -h, --help Display this help message");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_manifest_help(int argc, char** argv) {
|
||||
dpm_log(LOG_INFO, "Usage: dpm build manifest [options]");
|
||||
dpm_log(LOG_INFO, "");
|
||||
dpm_log(LOG_INFO, "Options:");
|
||||
dpm_log(LOG_INFO, " -s, --stage DIR Stage directory path (required)");
|
||||
dpm_log(LOG_INFO, " -r, --refresh-only Refresh existing manifest instead of generating a new one");
|
||||
dpm_log(LOG_INFO, " -f, --force Force manifest operation even if warnings occur");
|
||||
dpm_log(LOG_INFO, " -v, --verbose Enable verbose output");
|
||||
dpm_log(LOG_INFO, " -h, --help Display this help message");
|
||||
dpm_log(LOG_INFO, "");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* @file metadata.cpp
|
||||
* @brief Implementation of DPM package metadata functions
|
||||
*
|
||||
* Implements functions for creating and manipulating DPM package metadata.
|
||||
*
|
||||
* @copyright Copyright (c) 2025 SILO GROUP LLC
|
||||
* @author Chris Punches <chris.punches@silogroup.org>
|
||||
*
|
||||
* Part of the Dark Horse Linux Package Manager (DPM)
|
||||
*/
|
||||
|
||||
#include "metadata.hpp"
|
||||
|
||||
bool metadata_generate_new(
|
||||
const std::filesystem::path& package_dir,
|
||||
const std::string& package_name,
|
||||
const std::string& package_version,
|
||||
const std::string& architecture
|
||||
) {
|
||||
try {
|
||||
std::filesystem::path metadata_dir = package_dir / "metadata";
|
||||
|
||||
// Create NAME file
|
||||
{
|
||||
std::ofstream name_file(metadata_dir / "NAME");
|
||||
if (name_file.is_open()) {
|
||||
name_file << package_name;
|
||||
name_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Create VERSION file
|
||||
{
|
||||
std::ofstream version_file(metadata_dir / "VERSION");
|
||||
if (version_file.is_open()) {
|
||||
version_file << package_version;
|
||||
version_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Create ARCHITECTURE file
|
||||
{
|
||||
std::ofstream arch_file(metadata_dir / "ARCHITECTURE");
|
||||
if (arch_file.is_open()) {
|
||||
arch_file << architecture;
|
||||
arch_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Create empty placeholder files for other metadata
|
||||
std::vector<std::string> metadata_files = {
|
||||
"AUTHOR",
|
||||
"MAINTAINER",
|
||||
"DEPENDENCIES",
|
||||
"DESCRIPTION",
|
||||
"CONTENTS_MANIFEST_DIGEST",
|
||||
"LICENSE",
|
||||
"PACKAGE_DIGEST",
|
||||
"HOOKS_DIGEST",
|
||||
"PROVIDES",
|
||||
"REPLACES",
|
||||
"SOURCE",
|
||||
"CHANGELOG"
|
||||
};
|
||||
|
||||
for (const auto& file_name : metadata_files) {
|
||||
std::ofstream metadata_file(metadata_dir / file_name);
|
||||
metadata_file.close();
|
||||
}
|
||||
|
||||
dpm_log(LOG_INFO, "Created metadata files");
|
||||
|
||||
// Update the contents manifest
|
||||
if (!update_contents_manifest(package_dir)) {
|
||||
dpm_log(LOG_ERROR, "Failed to update contents manifest");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
dpm_log(LOG_ERROR, ("Failed to create metadata files: " + std::string(e.what())).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the contents manifest file for a package
|
||||
*
|
||||
* Creates the CONTENTS_MANIFEST_DIGEST file by scanning the contents directory
|
||||
* and generating a line for each file with control designation,
|
||||
* checksum, permissions, ownership, and path information.
|
||||
*
|
||||
* @param package_dir Root directory of the package being staged
|
||||
* @return true if manifest generation was successful, false otherwise
|
||||
*/
|
||||
bool update_contents_manifest(const std::filesystem::path& package_dir)
|
||||
{
|
||||
try {
|
||||
std::filesystem::path contents_dir = package_dir / "contents";
|
||||
std::filesystem::path manifest_path = package_dir / "metadata" / "CONTENTS_MANIFEST_DIGEST";
|
||||
|
||||
// Log which hash algorithm is being used
|
||||
std::string hash_algorithm = get_configured_hash_algorithm();
|
||||
dpm_log(LOG_INFO, ("Generating contents manifest using " + hash_algorithm + " checksums...").c_str());
|
||||
|
||||
// Open manifest file for writing
|
||||
std::ofstream manifest_file(manifest_path);
|
||||
if (!manifest_file.is_open()) {
|
||||
dpm_log(LOG_ERROR, ("Failed to open manifest file for writing: " + manifest_path.string()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process each file in the contents directory recursively
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(contents_dir)) {
|
||||
// Skip directories, we only need to record files
|
||||
if (std::filesystem::is_directory(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get file information
|
||||
std::filesystem::path file_path = entry.path();
|
||||
std::filesystem::path relative_path = std::filesystem::relative(file_path, contents_dir);
|
||||
std::string absolute_path = "/" + relative_path.string(); // Add leading slash
|
||||
|
||||
// Get file stats for permissions
|
||||
struct stat file_stat;
|
||||
if (stat(file_path.c_str(), &file_stat) != 0) {
|
||||
dpm_log(LOG_FATAL, ("Failed to get file stats for: " + file_path.string()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Format permissions as octal
|
||||
char perms[5];
|
||||
snprintf(perms, sizeof(perms), "%04o", file_stat.st_mode & 07777);
|
||||
|
||||
// Get owner and group information
|
||||
struct passwd* pw = getpwuid(file_stat.st_uid);
|
||||
struct group* gr = getgrgid(file_stat.st_gid);
|
||||
|
||||
std::string owner;
|
||||
if (pw) {
|
||||
owner = pw->pw_name;
|
||||
} else {
|
||||
owner = std::to_string(file_stat.st_uid);
|
||||
}
|
||||
|
||||
std::string group;
|
||||
if (gr) {
|
||||
group = gr->gr_name;
|
||||
} else {
|
||||
group = std::to_string(file_stat.st_gid);
|
||||
}
|
||||
|
||||
std::string ownership = owner + ":" + group;
|
||||
|
||||
// Calculate file checksum using the configured algorithm
|
||||
std::string checksum = generate_file_checksum(file_path);
|
||||
if (checksum.empty()) {
|
||||
dpm_log(LOG_FATAL, ("Failed to generate checksum for: " + file_path.string()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// By default, mark all files as controlled ('C')
|
||||
char control_designation = 'C';
|
||||
|
||||
// Write the manifest entry
|
||||
// Format: control_designation checksum permissions owner:group /absolute/path
|
||||
manifest_file << control_designation << " "
|
||||
<< checksum << " "
|
||||
<< perms << " "
|
||||
<< ownership << " "
|
||||
<< absolute_path << "\n";
|
||||
}
|
||||
|
||||
manifest_file.close();
|
||||
dpm_log(LOG_INFO, "Contents manifest generated successfully");
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
dpm_log(LOG_ERROR, ("Failed to generate contents manifest: " + std::string(e.what())).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -264,170 +264,6 @@ static bool stage_populate_hooks(
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool stage_populate_basic_metadata(
|
||||
const std::filesystem::path& package_dir,
|
||||
const std::string& package_name,
|
||||
const std::string& package_version,
|
||||
const std::string& architecture
|
||||
) {
|
||||
try {
|
||||
std::filesystem::path metadata_dir = package_dir / "metadata";
|
||||
|
||||
// Create NAME file
|
||||
{
|
||||
std::ofstream name_file(metadata_dir / "NAME");
|
||||
if (name_file.is_open()) {
|
||||
name_file << package_name;
|
||||
name_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Create VERSION file
|
||||
{
|
||||
std::ofstream version_file(metadata_dir / "VERSION");
|
||||
if (version_file.is_open()) {
|
||||
version_file << package_version;
|
||||
version_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Create ARCHITECTURE file
|
||||
{
|
||||
std::ofstream arch_file(metadata_dir / "ARCHITECTURE");
|
||||
if (arch_file.is_open()) {
|
||||
arch_file << architecture;
|
||||
arch_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Create empty placeholder files for other metadata
|
||||
std::vector<std::string> metadata_files = {
|
||||
"AUTHOR",
|
||||
"MAINTAINER",
|
||||
"DEPENDENCIES",
|
||||
"DESCRIPTION",
|
||||
"CONTENTS_MANIFEST_DIGEST",
|
||||
"LICENSE",
|
||||
"PACKAGE_DIGEST",
|
||||
"HOOKS_DIGEST",
|
||||
"PROVIDES",
|
||||
"REPLACES",
|
||||
"SOURCE",
|
||||
"CHANGELOG"
|
||||
};
|
||||
|
||||
for (const auto& file_name : metadata_files) {
|
||||
std::ofstream metadata_file(metadata_dir / file_name);
|
||||
metadata_file.close();
|
||||
}
|
||||
|
||||
dpm_log(LOG_INFO, "Created metadata files");
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
dpm_log(LOG_ERROR, ("Failed to create metadata files: " + std::string(e.what())).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the contents manifest file for a package
|
||||
*
|
||||
* Creates the CONTENTS_MANIFEST_DIGEST file by scanning the contents directory
|
||||
* and generating a line for each file with control designation,
|
||||
* checksum, permissions, ownership, and path information.
|
||||
*
|
||||
* @param package_dir Root directory of the package being staged
|
||||
* @return true if manifest generation was successful, false otherwise
|
||||
*/
|
||||
static bool update_contents_manifest(const std::filesystem::path& package_dir)
|
||||
{
|
||||
try {
|
||||
std::filesystem::path contents_dir = package_dir / "contents";
|
||||
std::filesystem::path manifest_path = package_dir / "metadata" / "CONTENTS_MANIFEST_DIGEST";
|
||||
|
||||
// Log which hash algorithm is being used
|
||||
std::string hash_algorithm = get_configured_hash_algorithm();
|
||||
dpm_log(LOG_INFO, ("Generating contents manifest using " + hash_algorithm + " checksums...").c_str());
|
||||
|
||||
// Open manifest file for writing
|
||||
std::ofstream manifest_file(manifest_path);
|
||||
if (!manifest_file.is_open()) {
|
||||
dpm_log(LOG_ERROR, ("Failed to open manifest file for writing: " + manifest_path.string()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process each file in the contents directory recursively
|
||||
for (const auto& entry : std::filesystem::recursive_directory_iterator(contents_dir)) {
|
||||
// Skip directories, we only need to record files
|
||||
if (std::filesystem::is_directory(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get file information
|
||||
std::filesystem::path file_path = entry.path();
|
||||
std::filesystem::path relative_path = std::filesystem::relative(file_path, contents_dir);
|
||||
std::string absolute_path = "/" + relative_path.string(); // Add leading slash
|
||||
|
||||
// Get file stats for permissions
|
||||
struct stat file_stat;
|
||||
if (stat(file_path.c_str(), &file_stat) != 0) {
|
||||
dpm_log(LOG_FATAL, ("Failed to get file stats for: " + file_path.string()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Format permissions as octal
|
||||
char perms[5];
|
||||
snprintf(perms, sizeof(perms), "%04o", file_stat.st_mode & 07777);
|
||||
|
||||
// Get owner and group information
|
||||
struct passwd* pw = getpwuid(file_stat.st_uid);
|
||||
struct group* gr = getgrgid(file_stat.st_gid);
|
||||
|
||||
std::string owner;
|
||||
if (pw) {
|
||||
owner = pw->pw_name;
|
||||
} else {
|
||||
owner = std::to_string(file_stat.st_uid);
|
||||
}
|
||||
|
||||
std::string group;
|
||||
if (gr) {
|
||||
group = gr->gr_name;
|
||||
} else {
|
||||
group = std::to_string(file_stat.st_gid);
|
||||
}
|
||||
|
||||
std::string ownership = owner + ":" + group;
|
||||
|
||||
// Calculate file checksum using the configured algorithm
|
||||
std::string checksum = generate_file_checksum(file_path);
|
||||
if (checksum.empty()) {
|
||||
dpm_log(LOG_FATAL, ("Failed to generate checksum for: " + file_path.string()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// By default, mark all files as controlled ('C')
|
||||
char control_designation = 'C';
|
||||
|
||||
// Write the manifest entry
|
||||
// Format: control_designation checksum permissions owner:group /absolute/path
|
||||
manifest_file << control_designation << " "
|
||||
<< checksum << " "
|
||||
<< perms << " "
|
||||
<< ownership << " "
|
||||
<< absolute_path << "\n";
|
||||
}
|
||||
|
||||
manifest_file.close();
|
||||
dpm_log(LOG_INFO, "Contents manifest generated successfully");
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
dpm_log(LOG_ERROR, ("Failed to generate contents manifest: " + std::string(e.what())).c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int build_package_stage(
|
||||
const std::string& output_dir,
|
||||
const std::string& contents_dir,
|
||||
|
@ -465,7 +301,7 @@ int build_package_stage(
|
|||
}
|
||||
|
||||
// Populate metadata files
|
||||
if (!stage_populate_basic_metadata(package_dir, package_name, package_version, architecture))
|
||||
if (!metadata_generate_new(package_dir, package_name, package_version, architecture))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue