Switched over to using uint64s, changed the eternity.json format

This commit is contained in:
Arzumify 2024-10-10 10:25:46 +01:00
parent a05c59b044
commit a316bcd73c
3 changed files with 53 additions and 200 deletions

BIN
cmd/cmd

Binary file not shown.

View file

@ -8,7 +8,6 @@ import (
"git.oreonproject.org/oreonproject/eternity/common"
"git.oreonproject.org/oreonproject/eternity/lib"
"math/big"
"os/signal"
"path/filepath"
@ -62,7 +61,7 @@ func main() {
os.Exit(1)
}
}()
var size big.Int
var size int64
size, tempDir, err, vagueError = lib.BuildEPK("./", inMemory, config.Build, logger)
if err != nil || vagueError != nil {
common.BuildEPKHandleError(tempDir, err, vagueError, logger)
@ -238,12 +237,12 @@ func main() {
Name: name,
Description: description,
LongDescription: longDescription,
Version: *semanticVersion,
Version: semanticVersion,
Author: author,
License: license,
Architecture: architecture,
Dependencies: dependencies,
DecompressedSize: *big.NewInt(int64(decompressedSize[0])),
DecompressedSize: int64(decompressedSize[0]),
SpecialFiles: lib.SpecialFiles{},
}
@ -267,9 +266,6 @@ func main() {
// Package the EPK
err, vagueError = lib.PackageEPK(metadata, lib.Build{
TargetRoot: "payload",
HooksFolder: lib.PotentiallyNullString{
Null: true,
},
}, tempDir, os.Args[3], privateKey, logger)
if err != nil || vagueError != nil {
common.PackageEPKHandleError(err, vagueError, logger)

View file

@ -12,7 +12,6 @@ import (
"crypto/ed25519"
"encoding/binary"
"encoding/json"
"math/big"
"os/exec"
"path/filepath"
@ -23,45 +22,40 @@ import (
// SpecialFiles is a struct that contains the special files that are not to be deleted or replaced
type SpecialFiles struct {
NoDelete []string
NoReplace []string
NoDelete []string `json:"noDelete"`
NoReplace []string `json:"noReplace"`
}
// Metadata is a struct that contains the metadata of the package
type Metadata struct {
Name string
Description string
LongDescription string
Version semver.Version
Author string
License string
Architecture string
Name string `json:"name"`
Description string `json:"desc"`
LongDescription string `json:"longDesc"`
Version *semver.Version
VersionString string `json:"version"`
Author string `json:"author"`
License string `json:"license"`
Architecture string `json:"arch"`
// The decompressed size may be larger than the int64 allocated for a compressed file
DecompressedSize big.Int
Dependencies []string
SpecialFiles SpecialFiles
DecompressedSize int64
Dependencies []string `json:"deps"`
SpecialFiles SpecialFiles `json:"specialFiles"`
}
// Build is a struct that contains the build configuration of the package
type Build struct {
Type string
Dependencies []string
Steps []string
TargetRoot string
HooksFolder PotentiallyNullString
FilesFolder PotentiallyNullString
}
// PotentiallyNullString is a struct that contains a string that may be null
type PotentiallyNullString struct {
Value string
Null bool
Type string `json:"type"`
Dependencies []string `json:"deps"`
Steps []string `json:"steps"`
TargetRoot string `json:"root"`
HooksFolder string `json:"hooks"`
FilesFolder string `json:"files"`
}
// Config is a struct that contains the configuration of the package
type Config struct {
Metadata Metadata
Build Build
Metadata Metadata `json:"metadata"`
Build Build `json:"build"`
}
// Log is a struct that contains the log information
@ -84,22 +78,6 @@ var ErrEternityJsonReadError = errors.New("error reading eternity.json")
var ErrEternityJsonParseError = errors.New("error parsing eternity.json")
var ErrEternityJsonMapError = errors.New("error mapping eternity.json")
// interfaceToStringSlice converts an interface slice to a string slice
func interfaceToStringSlice(interfaceSlice []interface{}, interfaceName string) ([]string, error) {
// Yes, it's meant to be empty and not nil: JSON arrays are empty, not nil
//goland:noinspection GoPreferNilSlice
stringSlice := []string{}
for _, interfaceValue := range interfaceSlice {
stringValue, ok := interfaceValue.(string)
if !ok {
return nil, errors.New(interfaceName + " are not strings")
}
stringSlice = append(stringSlice, stringValue)
}
return stringSlice, nil
}
// ParseConfig parses the eternity.json file
func ParseConfig(path string, logger *Logger) (Config, error, error) {
// Open eternity.json
@ -113,143 +91,22 @@ func ParseConfig(path string, logger *Logger) (Config, error, error) {
return Config{}, err, ErrEternityJsonOpenError
}
// Convert the file to a byte buffer
var fileBytes bytes.Buffer
_, err = io.Copy(&fileBytes, file)
if err != nil {
return Config{}, err, ErrEternityJsonReadError
}
// Parse the file as JSON
var config map[string]interface{}
err = json.Unmarshal(fileBytes.Bytes(), &config)
var config Config
decoder := json.NewDecoder(file)
err = decoder.Decode(&config)
if err != nil {
return Config{}, err, ErrEternityJsonParseError
}
// Map SpecialFiles
var parsedSpecialFiles SpecialFiles
specialFiles, ok := config["specialFiles"].(map[string]interface{})
if !ok {
return Config{}, errors.New("specialFiles is not an object"), ErrEternityJsonMapError
}
noDelete, ok := specialFiles["noDelete"].([]interface{})
if !ok {
return Config{}, errors.New("noDelete is not an array"), ErrEternityJsonMapError
}
parsedSpecialFiles.NoDelete, err = interfaceToStringSlice(noDelete, "noDelete")
// Map the JSON version to a semver version
config.Metadata.Version, err = semver.NewVersion(config.Metadata.VersionString)
if err != nil {
return Config{}, err, ErrEternityJsonMapError
}
noReplace, ok := specialFiles["noReplace"].([]interface{})
if !ok {
return Config{}, errors.New("noReplace is not an array"), ErrEternityJsonMapError
}
parsedSpecialFiles.NoReplace, err = interfaceToStringSlice(noReplace, "noReplace")
if err != nil {
return Config{}, err, ErrEternityJsonMapError
}
// Declare the parsedMetadata object
var parsedMetadata Metadata
// Append parsedSpecialFiles to parsedMetadata
parsedMetadata.SpecialFiles = parsedSpecialFiles
// Map the metadata
parsedMetadata.Name, ok = config["name"].(string)
if !ok {
return Config{}, errors.New("name is not a string"), ErrEternityJsonMapError
}
parsedMetadata.Description, ok = config["desc"].(string)
if !ok {
return Config{}, errors.New("description is not a string"), ErrEternityJsonMapError
}
parsedMetadata.LongDescription, ok = config["longDesc"].(string)
if !ok {
return Config{}, errors.New("longDesc is not a string"), ErrEternityJsonMapError
}
versionString, ok := config["version"].(string)
if !ok {
return Config{}, errors.New("version is not a string"), ErrEternityJsonMapError
}
versionPointer, err := semver.NewVersion(versionString)
if err != nil {
return Config{}, err, ErrEternityJsonMapError
}
parsedMetadata.Version = *versionPointer
parsedMetadata.Author, ok = config["author"].(string)
if !ok {
return Config{}, errors.New("author is not a string"), ErrEternityJsonMapError
}
parsedMetadata.License, ok = config["license"].(string)
if !ok {
return Config{}, errors.New("license is not a string"), ErrEternityJsonMapError
}
parsedMetadata.Architecture, ok = config["arch"].(string)
if !ok {
return Config{}, errors.New("arch is not a string"), ErrEternityJsonMapError
}
dependencies, ok := config["deps"].([]interface{})
if !ok {
return Config{}, errors.New("deps is not an array"), ErrEternityJsonMapError
}
parsedMetadata.Dependencies, err = interfaceToStringSlice(dependencies, "dependencies")
if err != nil {
return Config{}, err, ErrEternityJsonMapError
}
// Map build
var parsedBuild Build
build, ok := config["build"].(map[string]interface{})
if !ok {
return Config{}, errors.New("build is not an object"), ErrEternityJsonMapError
}
parsedBuild.Type, ok = build["type"].(string)
if !ok {
return Config{}, errors.New("type is not a string"), ErrEternityJsonMapError
}
buildDependencies, ok := build["deps"].([]interface{})
if !ok {
return Config{}, errors.New("deps is not an array"), ErrEternityJsonMapError
}
parsedBuild.Dependencies, err = interfaceToStringSlice(buildDependencies, "deps")
if err != nil {
return Config{}, err, ErrEternityJsonMapError
}
steps, ok := build["steps"].([]interface{})
if !ok {
return Config{}, errors.New("steps is not an array"), ErrEternityJsonMapError
}
parsedBuild.Steps, err = interfaceToStringSlice(steps, "steps")
if err != nil {
return Config{}, err, ErrEternityJsonMapError
}
parsedBuild.TargetRoot, ok = build["root"].(string)
if !ok {
return Config{}, errors.New("root is not a string"), ErrEternityJsonMapError
}
hooksFolder, ok := build["hooks"].(string)
if !ok {
parsedBuild.HooksFolder = PotentiallyNullString{Null: true}
} else {
parsedBuild.HooksFolder = PotentiallyNullString{Null: false, Value: hooksFolder}
}
filesFolder, ok := build["files"].(string)
if !ok {
parsedBuild.FilesFolder = PotentiallyNullString{Null: true}
} else {
parsedBuild.FilesFolder = PotentiallyNullString{Null: false, Value: filesFolder}
}
// Create the final Config object
parsedConfig := Config{
Metadata: parsedMetadata,
Build: parsedBuild,
}
// Return the final Config object
return parsedConfig, nil, nil
return config, nil, nil
}
var ErrBuildEPKTemporaryDirectoryError = errors.New("error creating temporary directory")
@ -265,14 +122,14 @@ var ErrBuildEPKCountingFilesError = errors.New("error counting files")
var ErrBuildEPKBadBuildType = errors.New("bad build type")
// BuildEPK builds the EPK package into a build directory
func BuildEPK(projectDir string, inMemory bool, buildConfig Build, logger *Logger) (big.Int, string, error, error) {
func BuildEPK(projectDir string, inMemory bool, buildConfig Build, logger *Logger) (int64, string, error, error) {
var tempDir string
switch buildConfig.Type {
case "chroot":
return *big.NewInt(0), "", nil, ErrBuildEPKChrootError
return 0, "", nil, ErrBuildEPKChrootError
case "unrestricted":
return *big.NewInt(0), "", nil, ErrBuildEPKUnrestrictedError
return 0, "", nil, ErrBuildEPKUnrestrictedError
case "host":
// Set up the temp dir
var err error
@ -286,25 +143,25 @@ func BuildEPK(projectDir string, inMemory bool, buildConfig Build, logger *Logge
tempDir, err = os.MkdirTemp(projectDir, "eternity-build-")
}
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKTemporaryDirectoryError
return 0, tempDir, err, ErrBuildEPKTemporaryDirectoryError
}
// Copy the hooks folder
if buildConfig.HooksFolder.Null != true {
hooksDir := filepath.Join(projectDir, buildConfig.HooksFolder.Value)
targetHooksDir := filepath.Join(tempDir, buildConfig.HooksFolder.Value)
if buildConfig.HooksFolder != "" {
hooksDir := filepath.Join(projectDir, buildConfig.HooksFolder)
targetHooksDir := filepath.Join(tempDir, buildConfig.HooksFolder)
logger.LogFunc(Log{
Level: "INFO", Content: "Copying hooks from " + hooksDir + " to " + targetHooksDir, Prompt: false,
})
err = os.MkdirAll(targetHooksDir, 0755)
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKCreateHooksError
return 0, tempDir, err, ErrBuildEPKCreateHooksError
}
err = os.CopyFS(targetHooksDir, os.DirFS(hooksDir))
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKCopyHooksError
return 0, tempDir, err, ErrBuildEPKCopyHooksError
}
}
@ -321,19 +178,19 @@ func BuildEPK(projectDir string, inMemory bool, buildConfig Build, logger *Logge
file, err := os.OpenFile(tempDir+"/build.sh", os.O_CREATE|os.O_RDWR, 0755)
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKBuildShError
return 0, tempDir, err, ErrBuildEPKBuildShError
}
_, err = file.WriteString(shellScript)
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKWritingBuildShError
return 0, tempDir, err, ErrBuildEPKWritingBuildShError
}
// Set up the target root
targetRoot := filepath.Join(tempDir, buildConfig.TargetRoot)
err = os.MkdirAll(targetRoot, 0755)
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKTargetRootError
return 0, tempDir, err, ErrBuildEPKTargetRootError
}
// Execute the shell script in BWrap
@ -365,10 +222,10 @@ func BuildEPK(projectDir string, inMemory bool, buildConfig Build, logger *Logge
"/bin/sh", "/eternity/build.sh",
}
if buildConfig.FilesFolder.Null != true {
if buildConfig.FilesFolder != "" {
arguments = arguments[:len(arguments)-4]
arguments = append(
arguments, "--bind", filepath.Join(projectDir, buildConfig.FilesFolder.Value), filepath.Join("/", buildConfig.FilesFolder.Value),
arguments, "--bind", filepath.Join(projectDir, buildConfig.FilesFolder), filepath.Join("/", buildConfig.FilesFolder),
"/usr/bin/fakeroot-tcp", "--",
"/bin/sh", "/eternity/build.sh",
)
@ -380,12 +237,12 @@ func BuildEPK(projectDir string, inMemory bool, buildConfig Build, logger *Logge
}
err = cmd.Run()
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKExecutingBuildShError
return 0, tempDir, err, ErrBuildEPKExecutingBuildShError
}
// Hopefully, the build was successful. Let's give the user a file and size count.
var fileCount int
var sizeCount big.Int
var sizeCount int64
// We start at -1 because the root directory is not counted
dirCount := -1
err = filepath.Walk(targetRoot, func(path string, info os.FileInfo, err error) error {
@ -395,23 +252,23 @@ func BuildEPK(projectDir string, inMemory bool, buildConfig Build, logger *Logge
fileCount++
}
// Both directories and files need to have their sizes counted
sizeCount.Add(&sizeCount, big.NewInt(info.Size()))
sizeCount += info.Size()
return nil
})
if err != nil {
return *big.NewInt(0), tempDir, err, ErrBuildEPKCountingFilesError
return 0, tempDir, err, ErrBuildEPKCountingFilesError
}
logger.LogFunc(Log{
Level: "INFO",
Content: "Build successful. " + strconv.Itoa(fileCount) + " files and " + strconv.Itoa(dirCount) +
" directories created," + " totalling " + sizeCount.String() + " bytes.",
" directories created," + " totalling " + strconv.FormatInt(sizeCount, 10) + " bytes.",
Prompt: false,
})
return sizeCount, tempDir, nil, nil
default:
return *big.NewInt(0), "", errors.New(buildConfig.Type), ErrBuildEPKBadBuildType
return 0, "", errors.New(buildConfig.Type), ErrBuildEPKBadBuildType
}
}
@ -539,8 +396,8 @@ func PackageEPK(metaData Metadata, build Build, tempDir string, output string, p
return err, ErrPackageEPKMoveToDistError
}
if build.HooksFolder.Null != true {
hooksDir := filepath.Join(tempDir, build.HooksFolder.Value)
if build.HooksFolder != "" {
hooksDir := filepath.Join(tempDir, build.HooksFolder)
err = os.Rename(hooksDir, distDir+"/hooks")
if err != nil {
return err, ErrPackageEPKMoveToDistError
@ -565,7 +422,7 @@ func PackageEPK(metaData Metadata, build Build, tempDir string, output string, p
"noDelete": metaData.SpecialFiles.NoDelete,
"noReplace": metaData.SpecialFiles.NoReplace,
},
"size": metaData.DecompressedSize.String(),
"size": metaData.DecompressedSize,
}
// Make the data template into a JSON string