diff --git a/cmd/cmd b/cmd/cmd index 1cf13f5..9a93c19 100755 Binary files a/cmd/cmd and b/cmd/cmd differ diff --git a/cmd/main.go b/cmd/main.go index 1800a51..a092fcb 100644 --- a/cmd/main.go +++ b/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) diff --git a/lib/main.go b/lib/main.go index 0e4918a..1c9da28 100644 --- a/lib/main.go +++ b/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