Switched over to using uint64s, changed the eternity.json format
This commit is contained in:
parent
a05c59b044
commit
a316bcd73c
3 changed files with 53 additions and 200 deletions
BIN
cmd/cmd
BIN
cmd/cmd
Binary file not shown.
10
cmd/main.go
10
cmd/main.go
|
@ -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)
|
||||
|
|
243
lib/main.go
243
lib/main.go
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue