package main import ( "flag" "fmt" "log" "os" "path/filepath" "runtime" "spitfire-builder/spitfire" "time" //"errors" ) var ( all bool buildFlag bool clean bool fullClean bool update bool prePatch bool postPatch bool skipPatchUpdate bool run bool compress bool target string version string component string arch string release string platform string upload bool uploadPath string sourceRepo = "https://hg.mozilla.org/releases/mozilla-release" patchesRepo = "https://weforge.xyz/Spitfire/Patcher.git" url = "https://spitfirebrowser.xyz/" licence = "AGPL-3.0" name = "Spitfire" packageName = "spitfire-browser" maintainer = "Internet Addict" initialDir string skipDeps bool ignoreErrors bool ) var errors []error // This is also in build.go. Great! This code is a mess. func init() { flag.StringVar(&target, "t", "", "Target location format: component-arch-release-platform") flag.BoolVar(&compress, "c", false, "Compress the build directory into a tar.gz file before uploading") flag.StringVar(&version, "v", "", "Specify version for the package. For nightly, use current date if not specified.") flag.StringVar(&component, "component", "browser", "Component name (default: browser)") flag.StringVar(&arch, "arch", runtime.GOARCH, "Architecture (default: system architecture)") flag.StringVar(&release, "release", "nightly", "Release type (default: nightly)") flag.StringVar(&platform, "platform", runtime.GOOS, "Platform (default: system platform)") flag.BoolVar(&all, "a", false, "Perform all steps (build, clean, update)") flag.BoolVar(&buildFlag, "b", false, "Build Spitfire") flag.BoolVar(&clean, "clean", false, "Revert uncommitted changes without removing build artifacts") flag.BoolVar(&fullClean, "full-clean", false, "Perform a full clean by removing all build artifacts (clobber)") flag.BoolVar(&update, "u", false, "Update Mozilla repository") flag.BoolVar(&prePatch, "pre-patch", false, "Apply pre-build patches") flag.BoolVar(&postPatch, "post-patch", false, "Apply post-build patches") flag.BoolVar(&skipPatchUpdate, "skip-patch-update", false, "Skip updating the patches repository") flag.BoolVar(&run, "r", false, "Run the project after build") flag.BoolVar(&upload, "upload", false, "Upload the compressed build file to SourceForge") flag.StringVar(&uploadPath, "upload-path", "", "Path to the file to upload if no build present") flag.BoolVar(&skipDeps, "skip-deps", false, "Skip checking for required system dependencies") flag.BoolVar(&ignoreErrors, "ignore-errors", false, "Processes all steps even if errors occur") flag.Bool("h", false, "Display help message") } func printHelp() { fmt.Println("Usage: go run . -p= -t= [-c|--compress] [-v|--version=] [-component=] [-arch=] [-release=] [-platform=]") flag.PrintDefaults() fmt.Println("Example: go run . --upload -c -a") os.Exit(0) } func handleError(err error) { if err != nil { errors = append(errors, err) if !ignoreErrors { log.Fatal(err) } } } func main() { flag.Parse() if flag.Lookup("h").Value.(flag.Getter).Get().(bool) { printHelp() } if !skipDeps { if err := spitfire.CheckDependencies(); err != nil { handleError(fmt.Errorf("system check failed: %w", err)) } } if version == "" && release == "nightly" { version = time.Now().Format("2006.01.02") } // Save the initial directory var err error initialDir, err = os.Getwd() if err != nil { handleError(fmt.Errorf("failed to get current directory: %w", err)) } var buildDir string if all || buildFlag || prePatch || postPatch || clean || update || run { buildDir, err = BuildProcess() if err != nil { handleError(fmt.Errorf("build process failed: %w", err)) } else if buildDir == "" && (buildFlag || all || run) { handleError(fmt.Errorf("build directory not found after build process")) } } if compress || upload { if err := PackageAndUploadProcess(buildDir); err != nil { handleError(fmt.Errorf("package/upload failed: %w", err)) } } spitfire.PrintErrors() if len(errors) > 0 { fmt.Fprintf(os.Stderr, "Exiting with %d error(s):\n", len(errors)) for _, e := range errors { fmt.Fprintf(os.Stderr, "- %v\n", e) } os.Exit(1) } else { os.Exit(0) } } func BuildProcess() (string, error) { sourcePath, err := spitfire.ResolvePath("./mozilla-release") if err != nil { return "", fmt.Errorf("resolve source path: %w", err) } var buildDir string if all { if err := spitfire.DownloadSource(sourcePath, sourceRepo); err != nil { return "", fmt.Errorf("download source: %w", err) } if err := spitfire.DiscardChanges(sourcePath); err != nil { return "", fmt.Errorf("discard changes: %w", err) } if err := spitfire.CleanBuild(sourcePath, fullClean); err != nil { return "", fmt.Errorf("clean build: %w", err) } if err := spitfire.UpdateRepo(sourcePath); err != nil { return "", fmt.Errorf("update repo: %w", err) } if err := spitfire.ApplyPatches(sourcePath, patchesRepo, "pre-compile-patches", filepath.Join(sourcePath, "patcher"), skipPatchUpdate); err != nil { return "", fmt.Errorf("pre-patch: %w", err) } if err := spitfire.Configure(sourcePath); err != nil { return "", fmt.Errorf("configure: %w", err) } if err := spitfire.Build(sourcePath); err != nil { return "", fmt.Errorf("build: %w", err) } buildDir, err = spitfire.ResolveBuildDir(sourcePath) if err != nil { return "", fmt.Errorf("resolve build dir: %w", err) } if err := spitfire.ApplyPatches(buildDir, patchesRepo, "post-compile-patches", filepath.Join(sourcePath, "patcher"), skipPatchUpdate); err != nil { return "", fmt.Errorf("post-patch: %w", err) } if run { if err := spitfire.RunProject(sourcePath); err != nil { return "", fmt.Errorf("run project: %w", err) } } fmt.Println("Spitfire build completed successfully.") } else if buildFlag { if prePatch { if err := spitfire.ApplyPatches(sourcePath, patchesRepo, "pre-compile-patches", filepath.Join(sourcePath, "patcher"), skipPatchUpdate); err != nil { return "", fmt.Errorf("pre-patch: %w", err) } } if err := spitfire.Configure(sourcePath); err != nil { return "", fmt.Errorf("configure: %w", err) } if err := spitfire.Build(sourcePath); err != nil { return "", fmt.Errorf("build: %w", err) } buildDir, err = spitfire.ResolveBuildDir(sourcePath) if err != nil { return "", fmt.Errorf("resolve build dir: %w", err) } if postPatch { if err := spitfire.ApplyPatches(buildDir, patchesRepo, "post-compile-patches", filepath.Join(sourcePath, "patcher"), skipPatchUpdate); err != nil { return "", fmt.Errorf("post-patch: %w", err) } } if run { if err := spitfire.RunProject(sourcePath); err != nil { return "", fmt.Errorf("run project: %w", err) } } fmt.Println("Spitfire build completed successfully.") } else if clean { if err := spitfire.CleanBuild(sourcePath, fullClean); err != nil { return "", fmt.Errorf("clean build: %w", err) } fmt.Println("Cleaned Firefox build.") } else if update { if err := spitfire.DownloadSource(sourcePath, sourceRepo); err != nil { return "", fmt.Errorf("download source: %w", err) } if err := spitfire.UpdateRepo(sourcePath); err != nil { return "", fmt.Errorf("update repo: %w", err) } fmt.Println("Mozilla repository updated.") } else if prePatch { if err := spitfire.DownloadSource(sourcePath, sourceRepo); err != nil { return "", fmt.Errorf("download source: %w", err) } if err := spitfire.ApplyPatches(sourcePath, patchesRepo, "pre-compile-patches", filepath.Join(sourcePath, "patcher"), skipPatchUpdate); err != nil { return "", fmt.Errorf("pre-patch: %w", err) } fmt.Println("Patches updated.") } else if postPatch { buildDir, err = spitfire.ResolveBuildDir(sourcePath) if err != nil { return "", fmt.Errorf("resolve build dir: %w", err) } if _, err := os.Stat(buildDir); err == nil { if err := spitfire.ApplyPatches(buildDir, patchesRepo, "post-compile-patches", filepath.Join(sourcePath, "patcher"), skipPatchUpdate); err != nil { return "", fmt.Errorf("post-patch: %w", err) } } if run { if err := spitfire.RunProject(sourcePath); err != nil { return "", fmt.Errorf("run project: %w", err) } } } else if run { if err := spitfire.RunProject(sourcePath); err != nil { return "", fmt.Errorf("run project: %w", err) } } return buildDir, nil } func PackageAndUploadProcess(buildDir string) error { restoreWorkingDirectory() pathToUse := buildDir if upload && uploadPath != "" { pathToUse = uploadPath } if pathToUse == "" { return fmt.Errorf("no valid build or upload path provided") } uncompressedSize, err := spitfire.GetDirectorySize(pathToUse) if err != nil { return fmt.Errorf("get directory size: %w", err) } fmt.Printf("Uncompressed directory size: %s\n", spitfire.BytesToHumanReadable(uncompressedSize)) outputCompressedFile := filepath.Join(".", fmt.Sprintf( "%s-%s-%s-%s.tar.gz", component, arch, release, platform, )) if compress { if err := spitfire.CompressDirectory(pathToUse, outputCompressedFile); err != nil { return fmt.Errorf("compress directory: %w", err) } fmt.Printf("Build directory compressed to: %s\n", outputCompressedFile) } compressedSize, err := spitfire.GetFileSize(outputCompressedFile) if err != nil { return fmt.Errorf("get compressed file size: %w", err) } fmt.Printf("Compressed file size: %s\n", spitfire.BytesToHumanReadable(compressedSize)) compressionRatio, efficiency := spitfire.CalculateCompressionEfficiency(uncompressedSize, compressedSize) fmt.Printf("Compression ratio: %.2f:1\n", compressionRatio) fmt.Printf("Compression efficiency: %.2f%%\n", efficiency) fmt.Printf("Compressed dir: %s\n", pathToUse) if !upload { return nil } config, err := spitfire.LoadConfig() if err != nil { return fmt.Errorf("load config: %w", err) } if _, err := os.Stat(outputCompressedFile); err != nil { return fmt.Errorf("compressed file not found: %w", err) } uploadDir := fmt.Sprintf("%s/%s/%s/%s", component, arch, release, version) if err := spitfire.Upload(config, outputCompressedFile, "/home/frs/project/spitfire-browser/"+uploadDir+"/"); err != nil { return fmt.Errorf("upload compressed file: %w", err) } fmt.Println("Compressed file uploaded successfully.") if err := spitfire.DownloadAPPINDEX(config, "/home/frs/project/spitfire-browser/"); err != nil { fmt.Println("Failed to download APPINDEX. A new one will be created and uploaded.") } if err := spitfire.PackageAPPINDEX( packageName, release, version, arch, fmt.Sprintf("%d", compressedSize), fmt.Sprintf("%d", uncompressedSize), name, url, licence, component, maintainer, "", platform, uploadDir, ); err != nil { return fmt.Errorf("package APPINDEX: %w", err) } fmt.Println("APPINDEX updated successfully.") if err := spitfire.CleanAppIndex(); err != nil { return fmt.Errorf("clean APPINDEX: %w", err) } if err := spitfire.UploadAPPINDEX(config, "/home/frs/project/spitfire-browser/"); err != nil { return fmt.Errorf("upload APPINDEX: %w", err) } fmt.Println("APPINDEX uploaded successfully.") return nil } func restoreWorkingDirectory() { if err := os.Chdir(initialDir); err != nil { log.Printf("Failed to restore working directory: %v", err) } }