mirror of
https://github.com/EnumeratedDev/bpm.git
synced 2026-09-16 02:26:12 +00:00
202 lines
5.8 KiB
Go
202 lines
5.8 KiB
Go
package bpmlib
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"gopkg.in/yaml.v3"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks bool) (err error) {
|
|
// Read BPM archive
|
|
bpmpkg, err := ReadPackage(archiveFilename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Ensure package type is 'source'
|
|
if bpmpkg.PkgInfo.Type != "source" {
|
|
return errors.New("cannot compile a non-source package")
|
|
}
|
|
|
|
// Get HOME directory
|
|
homeDir, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tempDirectory := path.Join(homeDir, ".cache/bpm/compilation/", bpmpkg.PkgInfo.Name)
|
|
|
|
// Ensure temporary directory does not exist
|
|
if _, err := os.Stat(tempDirectory); err == nil {
|
|
err := os.RemoveAll(tempDirectory)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Create temporary directory
|
|
err = os.MkdirAll(tempDirectory, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Extract source.sh file
|
|
err = extractTarballFile(archiveFilename, "source.sh", tempDirectory)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Get package scripts and extract them
|
|
packageScripts := getPackageScripts(archiveFilename)
|
|
for _, script := range packageScripts {
|
|
err = extractTarballFile(archiveFilename, script, tempDirectory)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Extract source files
|
|
err = extractTarballDirectory(archiveFilename, "source-files", tempDirectory)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create source directory
|
|
err = os.Mkdir(path.Join(tempDirectory, "source"), 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Setup environment for commands
|
|
env := os.Environ()
|
|
env = append(env, "HOME="+tempDirectory)
|
|
env = append(env, "BPM_WORKDIR="+tempDirectory)
|
|
env = append(env, "BPM_SOURCE="+path.Join(tempDirectory, "source"))
|
|
env = append(env, "BPM_OUTPUT="+path.Join(tempDirectory, "output"))
|
|
env = append(env, "BPM_PKG_NAME="+bpmpkg.PkgInfo.Name)
|
|
env = append(env, "BPM_PKG_VERSION="+bpmpkg.PkgInfo.Version)
|
|
env = append(env, "BPM_PKG_REVISION="+strconv.Itoa(bpmpkg.PkgInfo.Revision))
|
|
env = append(env, "BPM_PKG_ARCH="+GetArch())
|
|
env = append(env, BPMConfig.CompilationEnvironment...)
|
|
|
|
// Execute prepare and build functions in source.sh script
|
|
cmd := exec.Command("bash", "-c",
|
|
"set -a\n"+ // Source and export functions and variables in source.sh script
|
|
". \"${BPM_WORKDIR}\"/source.sh\n"+
|
|
"set +a\n"+
|
|
"[[ $(type -t prepare) == \"function\" ]] && (echo \"Running prepare() function\" && cd \"$BPM_SOURCE\" && set -e && prepare)\n"+ // Run prepare() function if it exists
|
|
"[[ $(type -t build) == \"function\" ]] && (echo \"Running build() function\" && cd \"$BPM_SOURCE\" && set -e && build)\n"+ // Run build() function if it exists
|
|
"exit 0")
|
|
cmd.Dir = tempDirectory
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Env = env
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Execute check function in source.sh script if not skipping checks
|
|
if !skipChecks {
|
|
cmd = exec.Command("bash", "-c",
|
|
"set -a\n"+ // Source and export functions and variables in source.sh script
|
|
". \"${BPM_WORKDIR}\"/source.sh\n"+
|
|
"set +a\n"+
|
|
"[[ $(type -t check) == \"function\" ]] && (echo \"Running check() function\" && cd \"$BPM_SOURCE\" && set -e && check)\n"+ // Run check() function if it exists
|
|
"exit 0")
|
|
cmd.Dir = tempDirectory
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Env = env
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Remove 'output' directory if it already exists
|
|
if _, err := os.Stat(path.Join(tempDirectory, "output")); err == nil {
|
|
err := os.RemoveAll(path.Join(tempDirectory, "output"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Create new 'output' directory
|
|
err = os.Mkdir(path.Join(tempDirectory, "output"), 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Run bash command
|
|
cmd = exec.Command("bash", "-e", "-c",
|
|
"set -a\n"+ // Source and export functions and variables in source.sh script
|
|
". \"${BPM_WORKDIR}\"/source.sh\n"+
|
|
"set +a\n"+
|
|
"(echo \"Running package() function\" && cd \"$BPM_SOURCE\" && fakeroot -s \"$BPM_WORKDIR\"/fakeroot_file package)\n"+ // Run package() function
|
|
"fakeroot -i \"$BPM_WORKDIR\"/fakeroot_file find \"$BPM_OUTPUT\" -mindepth 1 -printf \"%P %#m %U %G %s\\n\" > \"$BPM_WORKDIR\"/pkg.files") // Create package file list
|
|
cmd.Dir = tempDirectory
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Env = env
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create gzip-compressed archive for the package files
|
|
cmd = exec.Command("bash", "-c", "find output -printf \"%P\\n\" | fakeroot -i \"$BPM_WORKDIR\"/fakeroot_file tar -czf files.tar.gz --no-recursion -C output -T -")
|
|
cmd.Dir = tempDirectory
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Env = env
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
return fmt.Errorf("files.tar.gz archive could not be created: %s", err)
|
|
}
|
|
|
|
// Copy pkgInfo struct and set package type to binary
|
|
pkgInfo := bpmpkg.PkgInfo
|
|
pkgInfo.Type = "binary"
|
|
|
|
// Marshal package info
|
|
pkgInfoBytes, err := yaml.Marshal(pkgInfo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pkgInfoBytes = append(pkgInfoBytes, '\n')
|
|
|
|
// Create pkg.info file
|
|
err = os.WriteFile(path.Join(tempDirectory, "pkg.info"), pkgInfoBytes, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Get files to include in BPM archive
|
|
bpmArchiveFiles := make([]string, 0)
|
|
bpmArchiveFiles = append(bpmArchiveFiles, "pkg.info", "pkg.files", "files.tar.gz") // Base files
|
|
bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts
|
|
|
|
// Create final BPM archive
|
|
cmd = exec.Command("bash", "-c", "tar -cf "+outputFilename+" --owner=0 --group=0 -C \"$BPM_WORKDIR\" "+strings.Join(bpmArchiveFiles, " "))
|
|
cmd.Dir = tempDirectory
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
currentDir, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cmd.Env = append(env, "CURRENT_DIR="+currentDir)
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
return fmt.Errorf("BPM archive could not be created: %s", err)
|
|
}
|
|
|
|
return nil
|
|
}
|