summaryrefslogtreecommitdiff
path: root/src/libctor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libctor.cc')
-rw-r--r--src/libctor.cc124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/libctor.cc b/src/libctor.cc
index 2685ec0..6e6bcaf 100644
--- a/src/libctor.cc
+++ b/src/libctor.cc
@@ -16,6 +16,7 @@
#include <fstream>
#include <cstdlib>
#include <span>
+#include <set>
#include "ctor.h"
#include "configure.h"
@@ -26,6 +27,13 @@
#include "argparser.h"
#include "util.h"
+extern "C" {
+#include <archive.h>
+#include <archive_entry.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+}
+
int main(int argc, char* argv[])
{
auto args = std::span(argv, static_cast<std::size_t>(argc));
@@ -382,6 +390,122 @@ Options:
return ret;
}
}
+ else if(arg == "dist")
+ {
+ ctor::project project{};
+ std::set<std::string> dist_files;
+ auto& targets = getTargets(settings);
+ for(const auto& target : targets)
+ {
+ if(!target.config.project.name.empty())
+ {
+ project = target.config.project;
+ }
+
+ for(const auto& source : target.config.sources)
+ {
+ if(source.nodist)
+ {
+ continue;
+ }
+ std::filesystem::path p = target.path;
+ p /= source.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+ for(const auto& header : target.config.headers)
+ {
+ if(header.nodist)
+ {
+ continue;
+ }
+ std::filesystem::path p = target.path;
+ p /= header.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+ for(const auto& extra_dist_file : target.config.extra_dist)
+ {
+ if(extra_dist_file.nodist)
+ {
+ continue;
+ }
+ std::filesystem::path p = target.path;
+ p /= extra_dist_file.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+ }
+
+ const auto& configFiles = getConfigFileList();
+ for(const auto& configFile : configFiles)
+ {
+ std::filesystem::path p = configFile.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+
+ const auto& externalConfigFiles = getExternalConfigFileList();
+ for(const auto& externalConfigFile : externalConfigFiles)
+ {
+ std::filesystem::path p = externalConfigFile.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+
+ if(project.name.empty())
+ {
+ std::cerr << "Missing ctor::project description."
+ " Cannot create dist-file.\n";
+ return 1;
+ }
+ std::string outname = project.name + "-" +
+ std::to_string(project.version.major) + "." +
+ std::to_string(project.version.minor) + "." +
+ std::to_string(project.version.patch);
+ if(!project.version.tweak.empty())
+ {
+ outname += "-" + project.version.tweak;
+ }
+ outname += ".tar.gz";
+ {
+ struct archive *a;
+ struct archive_entry *entry;
+ struct stat st;
+ char buff[8192];
+ ssize_t len;
+ int fd;
+
+ a = archive_write_new();
+ // Filters: https://man.archlinux.org/man/archive_write_filter.3.en
+ archive_write_add_filter_gzip(a);
+ archive_write_set_format_pax_restricted(a); // Note 1
+ archive_write_open_filename(a, outname.data());
+
+ for(const auto& dist_file : dist_files)
+ {
+ const char*filename = dist_file.data();
+ stat(filename, &st);
+ auto mode = st.st_mode & 0xfff;//0644
+ std::cout << dist_file << std::oct << mode << '\n';
+ entry = archive_entry_new(); // Note 2
+ archive_entry_set_pathname(entry, filename);
+ archive_entry_set_size(entry, st.st_size); // Note 3
+ archive_entry_set_mtime(entry, st.st_mtime, 0);
+ archive_entry_set_filetype(entry, AE_IFREG);
+ archive_entry_set_perm(entry, mode);
+ archive_write_header(a, entry);
+ fd = open(filename, O_RDONLY);
+ len = read(fd, buff, sizeof(buff));
+ while ( len > 0 )
+ {
+ archive_write_data(a, buff, len);
+ len = read(fd, buff, sizeof(buff));
+ }
+ close(fd);
+ archive_entry_free(entry);
+ }
+
+ archive_write_close(a); // Note 4
+ archive_write_free(a); // Note 5
+ }
+ return 0;
+ }
else
{
build_all = false;