diff options
Diffstat (limited to 'src/libctor.cc')
| -rw-r--r-- | src/libctor.cc | 124 |
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; |
