|
@@ -0,0 +1,280 @@
|
|
|
|
|
+using Invercargill;
|
|
|
|
|
+using Invercargill.DataStructures;
|
|
|
|
|
+
|
|
|
|
|
+private int scaffold_main(string[] args) {
|
|
|
|
|
+ if(args.length < 4) {
|
|
|
|
|
+ return scaffold_usage();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var name = args[2];
|
|
|
|
|
+ var template = args[3];
|
|
|
|
|
+
|
|
|
|
|
+ // Parse attributes
|
|
|
|
|
+ var attributes = new HashSet<string>();
|
|
|
|
|
+ for(int i = 4; i < args.length; i++) {
|
|
|
|
|
+ attributes.add(args[i]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // Create the manifest based on template and attributes
|
|
|
|
|
+ var manifest = create_manifest(name, template, attributes);
|
|
|
|
|
+
|
|
|
|
|
+ // Write MANIFEST.usm file
|
|
|
|
|
+ write_manifest_file(manifest);
|
|
|
|
|
+
|
|
|
|
|
+ // Create scripts directory and scripts based on template
|
|
|
|
|
+ create_scripts(template, attributes);
|
|
|
|
|
+
|
|
|
|
|
+ print(@"Successfully scaffolded project '$name' with template '$template'\n");
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ catch(Error e) {
|
|
|
|
|
+ printerr(@"Error: $(e.message)\n");
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private int scaffold_usage() {
|
|
|
|
|
+ printerr("USAGE:\n\tusm scaffold <name> <template> [attributes...]\n");
|
|
|
|
|
+ printerr("\nTemplates:\n");
|
|
|
|
|
+ printerr("\tbasic - Creates only MANIFEST.usm\n");
|
|
|
|
|
+ printerr("\tmakefile - Creates MANIFEST.usm with make build scripts\n");
|
|
|
|
|
+ printerr("\tmeson - Creates MANIFEST.usm with meson build scripts\n");
|
|
|
|
|
+ printerr("\nAttributes:\n");
|
|
|
|
|
+ printerr("\tvala - Add Vala language dependencies\n");
|
|
|
|
|
+ printerr("\tc - Add C language dependencies\n");
|
|
|
|
|
+ printerr("\tacquire - Add acquire dependencies and script\n");
|
|
|
|
|
+ return 255;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private Usm.Manifest create_manifest(string name, string template, HashSet<string> attributes) throws Error {
|
|
|
|
|
+ var manifest = new Usm.Manifest();
|
|
|
|
|
+
|
|
|
|
|
+ // Basic manifest fields
|
|
|
|
|
+ manifest.name = name;
|
|
|
|
|
+ manifest.version = new Usm.Version.from_string("0.1.0");
|
|
|
|
|
+ manifest.summary = @"$name project";
|
|
|
|
|
+ manifest.licences = new Vector<Usm.Licence>();
|
|
|
|
|
+ manifest.licences.add(new Usm.Licence() { name = "MIT", category = Usm.LicenceCategory.LIBRE });
|
|
|
|
|
+
|
|
|
|
|
+ // Dependencies
|
|
|
|
|
+ manifest.dependencies = new Usm.Dependencies();
|
|
|
|
|
+ manifest.dependencies.runtime = new HashSet<Usm.ResourceRef>();
|
|
|
|
|
+ manifest.dependencies.build = new HashSet<Usm.ResourceRef>();
|
|
|
|
|
+ manifest.dependencies.manage = new HashSet<Usm.ResourceRef>();
|
|
|
|
|
+
|
|
|
|
|
+ // Executables
|
|
|
|
|
+ manifest.executables = new Usm.Executables();
|
|
|
|
|
+ manifest.flags = new HashSet<Usm.ManifestFlag>();
|
|
|
|
|
+
|
|
|
|
|
+ // Template-specific configurations
|
|
|
|
|
+ switch(template) {
|
|
|
|
|
+ case "basic":
|
|
|
|
|
+ manifest.executables.build = "usm-scripts/build.sh";
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case "makefile":
|
|
|
|
|
+ manifest.executables.build = "usm-scripts/build.sh";
|
|
|
|
|
+ manifest.executables.install = "usm-scripts/install.sh";
|
|
|
|
|
+ manifest.dependencies.manage.add(new Usm.ResourceRef("bin:bash"));
|
|
|
|
|
+ manifest.dependencies.build.add(new Usm.ResourceRef("bin:make"));
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case "meson":
|
|
|
|
|
+ manifest.executables.build = "usm-scripts/build.sh";
|
|
|
|
|
+ manifest.executables.install = "usm-scripts/install.sh";
|
|
|
|
|
+ manifest.dependencies.manage.add(new Usm.ResourceRef("bin:bash"));
|
|
|
|
|
+ manifest.dependencies.build.add(new Usm.ResourceRef("bin:meson"));
|
|
|
|
|
+ manifest.dependencies.build.add(new Usm.ResourceRef("bin:ninja"));
|
|
|
|
|
+ manifest.flags.add(Usm.ManifestFlag.NINJA_STYLE_PROGRESS);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ throw new Error(Quark.from_string("scaffold"), 1, @"Unknown template '$template'");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Apply attributes
|
|
|
|
|
+ if(attributes.contains("vala")) {
|
|
|
|
|
+ manifest.dependencies.build.add(new Usm.ResourceRef("bin:valac"));
|
|
|
|
|
+ manifest.dependencies.build.add(new Usm.ResourceRef("pc:glib-2.0.pc"));
|
|
|
|
|
+ manifest.dependencies.build.add(new Usm.ResourceRef("pc:gobject-2.0.pc"));
|
|
|
|
|
+ manifest.dependencies.runtime.add(new Usm.ResourceRef("lib:libc.so"));
|
|
|
|
|
+ manifest.dependencies.runtime.add(new Usm.ResourceRef("lib:libglib-2.0.so"));
|
|
|
|
|
+ manifest.dependencies.runtime.add(new Usm.ResourceRef("lib:libgobject-2.0.so"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(attributes.contains("c")) {
|
|
|
|
|
+ manifest.dependencies.build.add(new Usm.ResourceRef("bin:gcc"));
|
|
|
|
|
+ manifest.dependencies.runtime.add(new Usm.ResourceRef("lib:libc.so"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(attributes.contains("acquire")) {
|
|
|
|
|
+ manifest.dependencies.acquire = new HashSet<Usm.ResourceRef>();
|
|
|
|
|
+ manifest.dependencies.acquire.add(new Usm.ResourceRef("bin:bash"));
|
|
|
|
|
+ manifest.dependencies.acquire.add(new Usm.ResourceRef("bin:wget"));
|
|
|
|
|
+ manifest.dependencies.acquire.add(new Usm.ResourceRef("bin:tar"));
|
|
|
|
|
+ manifest.executables.acquire = "usm-scripts/acquire.sh";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return manifest;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private void write_manifest_file(Usm.Manifest manifest) throws Error {
|
|
|
|
|
+ var mapper = Usm.Manifest.get_mapper();
|
|
|
|
|
+ var properties = mapper.map_from(manifest);
|
|
|
|
|
+ var json_element = new InvercargillJson.JsonElement.from_properties(properties);
|
|
|
|
|
+
|
|
|
|
|
+ json_element.write_to_file("MANIFEST.usm");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private void create_scripts(string template, HashSet<string> attributes) throws Error {
|
|
|
|
|
+ // Create usm-scripts directory
|
|
|
|
|
+ var scripts_dir = File.new_for_path("usm-scripts");
|
|
|
|
|
+ if(!scripts_dir.query_exists()) {
|
|
|
|
|
+ scripts_dir.make_directory_with_parents();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Create build script
|
|
|
|
|
+ var build_script = File.new_for_path("usm-scripts/build.sh");
|
|
|
|
|
+ create_build_script(build_script, template);
|
|
|
|
|
+
|
|
|
|
|
+ // Create install script if needed
|
|
|
|
|
+ if(template == "makefile" || template == "meson") {
|
|
|
|
|
+ var install_script = File.new_for_path("usm-scripts/install.sh");
|
|
|
|
|
+ create_install_script(install_script, template);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Create acquire script if needed
|
|
|
|
|
+ if(attributes.contains("acquire")) {
|
|
|
|
|
+ var acquire_script = File.new_for_path("usm-scripts/acquire.sh");
|
|
|
|
|
+ create_acquire_script(acquire_script);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private void create_build_script(File file, string template) throws Error {
|
|
|
|
|
+ string content;
|
|
|
|
|
+
|
|
|
|
|
+ switch(template) {
|
|
|
|
|
+ case "basic":
|
|
|
|
|
+ content = """#!/bin/bash
|
|
|
|
|
+set -e
|
|
|
|
|
+
|
|
|
|
|
+src_dir=$(pwd)
|
|
|
|
|
+build_dir=$1
|
|
|
|
|
+
|
|
|
|
|
+# Basic build script
|
|
|
|
|
+echo "Building $(basename $(pwd))..."
|
|
|
|
|
+# Add your build commands here
|
|
|
|
|
+
|
|
|
|
|
+echo "Build completed successfully"
|
|
|
|
|
+""";
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case "makefile":
|
|
|
|
|
+ content = """#!/bin/bash
|
|
|
|
|
+set -e
|
|
|
|
|
+
|
|
|
|
|
+src_dir=$(pwd)
|
|
|
|
|
+build_dir=$1
|
|
|
|
|
+
|
|
|
|
|
+cd ${build_dir}
|
|
|
|
|
+
|
|
|
|
|
+make
|
|
|
|
|
+""";
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case "meson":
|
|
|
|
|
+ content = """#!/bin/bash
|
|
|
|
|
+set -e
|
|
|
|
|
+
|
|
|
|
|
+src_dir=$(pwd)
|
|
|
|
|
+build_dir=$1
|
|
|
|
|
+
|
|
|
|
|
+cd ${build_dir}
|
|
|
|
|
+
|
|
|
|
|
+meson setup ${src_dir}/src --prefix=${PREFIX} --libdir=${LIBDIR} --bindir=${BINDIR} --includedir=${INCLUDEDIR}
|
|
|
|
|
+ninja
|
|
|
|
|
+""";
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ throw new Error(Quark.from_string("scaffold"), 1, @"Unknown template '$template' for build script");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ write_script_file(file, content);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private void create_install_script(File file, string template) throws Error {
|
|
|
|
|
+ string content = get_script_header();
|
|
|
|
|
+
|
|
|
|
|
+ switch(template) {
|
|
|
|
|
+ case "makefile":
|
|
|
|
|
+ content += """src_dir=$(pwd)
|
|
|
|
|
+build_dir=$1
|
|
|
|
|
+install_dir=$2
|
|
|
|
|
+
|
|
|
|
|
+cd ${build_dir}
|
|
|
|
|
+
|
|
|
|
|
+make install DESTDIR=${install_dir}
|
|
|
|
|
+""";
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case "meson":
|
|
|
|
|
+ content += """src_dir=$(pwd)
|
|
|
|
|
+build_dir=$1
|
|
|
|
|
+install_dir=$2
|
|
|
|
|
+
|
|
|
|
|
+cd ${build_dir}
|
|
|
|
|
+
|
|
|
|
|
+meson install --destdir ${install_dir}
|
|
|
|
|
+""";
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ throw new Error(Quark.from_string("scaffold"), 1, @"Unknown template '$template' for install script");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ write_script_file(file, content);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private void create_acquire_script(File file) throws Error {
|
|
|
|
|
+ string content = get_script_header();
|
|
|
|
|
+
|
|
|
|
|
+ content += """# Acquire script - download and extract source archive
|
|
|
|
|
+# Replace these placeholders with actual values
|
|
|
|
|
+ARCHIVE_URL="https://example.com/source.tar.gz"
|
|
|
|
|
+ARCHIVE_NAME="source.tar.gz"
|
|
|
|
|
+EXTRACT_DIR="source"
|
|
|
|
|
+
|
|
|
|
|
+echo "Downloading source archive..."
|
|
|
|
|
+wget -O ${ARCHIVE_NAME} ${ARCHIVE_URL}
|
|
|
|
|
+
|
|
|
|
|
+echo "Extracting archive..."
|
|
|
|
|
+mkdir -p ${EXTRACT_DIR}
|
|
|
|
|
+tar -xzf ${ARCHIVE_NAME} -C ${EXTRACT_DIR} --strip-components=1
|
|
|
|
|
+
|
|
|
|
|
+echo "Cleaning up..."
|
|
|
|
|
+rm ${ARCHIVE_NAME}
|
|
|
|
|
+
|
|
|
|
|
+echo "Acquisition completed successfully"
|
|
|
|
|
+""";
|
|
|
|
|
+
|
|
|
|
|
+ write_script_file(file, content);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private string get_script_header() {
|
|
|
|
|
+ return """#!/bin/bash
|
|
|
|
|
+set -e
|
|
|
|
|
+""";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private void write_script_file(File file, string content) throws Error {
|
|
|
|
|
+ var data_stream = new DataOutputStream(file.replace(null, false, FileCreateFlags.NONE));
|
|
|
|
|
+ data_stream.put_string(content);
|
|
|
|
|
+
|
|
|
|
|
+ // Set execute bit
|
|
|
|
|
+ var file_info = file.query_info("*", FileQueryInfoFlags.NONE);
|
|
|
|
|
+ var mode = file_info.get_attribute_uint32("unix::mode");
|
|
|
|
|
+ mode |= 0111; // Add execute bit for owner, group, and others
|
|
|
|
|
+ file.set_attribute_uint32("unix::mode", mode, FileQueryInfoFlags.NONE);
|
|
|
|
|
+}
|