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("๐Ÿ“– Spitfire Build System Help") fmt.Println("Usage: go run . [options]") fmt.Println("") fmt.Println("๐Ÿš€ Main Operations:") fmt.Println("") fmt.Println("๐Ÿ”ง Build Options:") fmt.Println(" -a, -all Perform all steps (build, clean, update)") fmt.Println(" -b, -build Build Spitfire") fmt.Println(" -r, -run Run the project after build") fmt.Println("") fmt.Println("๐Ÿงน Clean Options:") fmt.Println(" -clean Revert uncommitted changes") fmt.Println(" -full-clean Remove all build artifacts (clobber)") fmt.Println("") fmt.Println("๐Ÿ”„ Update Options:") fmt.Println(" -u, -update Update Mozilla repository") fmt.Println(" -pre-patch Apply pre-build patches") fmt.Println(" -post-patch Apply post-build patches") fmt.Println(" -skip-patch-update Skip updating patches repository") fmt.Println("") fmt.Println("๐Ÿ“ฆ Package Options:") fmt.Println(" -c, -compress Compress build directory to tar.gz") fmt.Println(" -upload Upload compressed file to SourceForge") fmt.Println(" -upload-path Path to file for upload") fmt.Println("") fmt.Println("โš™๏ธ Configuration Options:") fmt.Println(" -t, -target Target format: component-arch-release-platform") fmt.Println(" -v, -version Package version (default: date for nightly)") fmt.Println(" -component Component name (default: browser)") fmt.Println(" -arch Architecture (default: system arch)") fmt.Println(" -release Release type (default: nightly)") fmt.Println(" -platform Platform (default: system OS)") fmt.Println("") fmt.Println("๐Ÿ” Other Options:") fmt.Println(" -skip-deps Skip system dependency checks") fmt.Println(" -ignore-errors Continue despite errors") fmt.Println(" -h, -help Show this help message") fmt.Println("") fmt.Println("๐Ÿ’ก Examples:") fmt.Println(" Full build and upload: go run . -a -c -upload") fmt.Println(" Just build: go run . -b") fmt.Println(" Clean build: go run . -clean") fmt.Println(" Upload existing: go run . -upload -upload-path=./build.tar.gz") fmt.Println("") fmt.Println("๐ŸŒ Project: https://weforge.xyz/Spitfire") 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() } fmt.Println("๐Ÿš€ Starting Spitfire build process...") if !skipDeps { fmt.Println("๐Ÿ” Checking system dependencies...") if err := spitfire.CheckDependencies(); err != nil { handleError(fmt.Errorf("โŒ system check failed: %w", err)) } fmt.Println("โœ… All dependencies verified") } if version == "" && release == "nightly" { version = time.Now().Format("2006.01.02") fmt.Printf("๐Ÿ“… Using nightly version: %s\n", version) } // 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 { fmt.Println("๐Ÿ—๏ธ Starting build process...") 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 { fmt.Println("๐Ÿ“ฆ Packaging and uploading build...") 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 { fmt.Println("๐ŸŽ‰ All operations completed successfully!") os.Exit(0) } } func BuildProcess() (string, error) { fmt.Println("๐Ÿ“‚ Resolving source path...") sourcePath, err := spitfire.ResolvePath("./mozilla-release") if err != nil { return "", fmt.Errorf("โŒ resolve source path: %w", err) } var buildDir string if all { fmt.Println("๐Ÿ”„ Running full build process...") 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 { fmt.Println("๐Ÿ”จ Running build process...") 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 { fmt.Println("๐Ÿงน Cleaning build...") if err := spitfire.CleanBuild(sourcePath, fullClean); err != nil { return "", fmt.Errorf("โŒ clean build: %w", err) } fmt.Println("โœ… Firefox build cleaned") } else if update { fmt.Println("๐Ÿ”„ Updating repository...") 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 { fmt.Println("๐Ÿ”ง Applying pre-compile patches...") 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("โœ… Pre-compile patches applied") } else if postPatch { fmt.Println("๐Ÿ”ง Applying post-compile patches...") 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 { fmt.Println("๐Ÿš€ Running project...") if err := spitfire.RunProject(sourcePath); err != nil { return "", fmt.Errorf("โŒ run project: %w", err) } } return buildDir, nil } func PackageAndUploadProcess(buildDir string) error { fmt.Println("๐Ÿ“ฆ Starting package and upload process...") restoreWorkingDirectory() pathToUse := buildDir if upload && uploadPath != "" { pathToUse = uploadPath fmt.Printf(" โ”œโ”€ Using custom upload path: %s\n", pathToUse) } if pathToUse == "" { return fmt.Errorf("โŒ no valid build or upload path provided") } fmt.Println("๐Ÿ“ Calculating directory size...") uncompressedSize, err := spitfire.GetDirectorySize(pathToUse) if err != nil { return fmt.Errorf("โŒ get directory size: %w", err) } fmt.Printf(" โ”œโ”€ Uncompressed size: %s\n", spitfire.BytesToHumanReadable(uncompressedSize)) outputCompressedFile := filepath.Join(".", fmt.Sprintf( "%s-%s-%s-%s.tar.gz", component, arch, release, platform, )) fmt.Printf(" โ”œโ”€ Output filename: %s\n", outputCompressedFile) if compress { fmt.Println("๐Ÿ—œ๏ธ Compressing directory...") 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 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(" โ””โ”€ Source directory: %s\n", pathToUse) if !upload { fmt.Println("โฉ Upload skipped (not requested)") return nil } fmt.Println("๐Ÿ”‘ Loading configuration...") 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) fmt.Printf("๐Ÿ“ค Uploading to: %s\n", uploadDir) 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") fmt.Println("๐Ÿ“ฅ Downloading APPINDEX...") if err := spitfire.DownloadAPPINDEX(config, "/home/frs/project/spitfire-browser/"); err != nil { fmt.Println("โš ๏ธ Failed to download APPINDEX - creating new one") } fmt.Println("๐Ÿ“ Updating APPINDEX...") 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") fmt.Println("๐Ÿงน Cleaning APPINDEX...") if err := spitfire.CleanAppIndex(); err != nil { return fmt.Errorf("โŒ clean APPINDEX: %w", err) } fmt.Println("๐Ÿ“ค Uploading APPINDEX...") 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() { fmt.Println("โ†ฉ๏ธ Restoring working directory...") if err := os.Chdir(initialDir); err != nil { log.Printf("โš ๏ธ Failed to restore working directory: %v", err) } }