Builder/spitfire/build.go
2024-09-10 23:21:46 +02:00

213 lines
6.8 KiB
Go

package spitfire
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
)
// Array to store errors
var errors []string
// Check and Set MOZILLABUILD environment variable automatically
func setMozillaBuildEnv() error {
// Check if MOZILLABUILD is already set
if os.Getenv("MOZILLABUILD") != "" {
fmt.Println("MOZILLABUILD environment variable is already set.")
return nil
}
// Try to detect the MozillaBuild installation directory
defaultPaths := []string{
"C:\\mozilla-build",
"C:\\Program Files\\mozilla-build",
"C:\\Program Files (x86)\\mozilla-build",
}
for _, path := range defaultPaths {
if _, err := os.Stat(path); !os.IsNotExist(err) {
// Set the MOZILLABUILD environment variable
fmt.Printf("Setting MOZILLABUILD environment variable to: %s\n", path)
return os.Setenv("MOZILLABUILD", path)
}
}
// If no directory was found, return an error
return fmt.Errorf("MozillaBuild directory not found. Please install MozillaBuild or set the MOZILLABUILD environment variable manually.")
}
// Run an external command like scp or rsync
func runCommand(command string, args ...string) error {
// Make sure the MOZILLABUILD environment variable is set for the mach commands
if err := setMozillaBuildEnv(); err != nil {
return err
}
cmd := exec.Command(command, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
// Function to resolve paths using absolute path
func ResolvePath(path string) (string, error) {
// Convert Unix-style slashes to the platform's native slashes
path = filepath.FromSlash(path)
// Get the absolute path
absPath, err := filepath.Abs(path)
if err != nil {
return "", fmt.Errorf("failed to resolve path: %s, error: %v", path, err)
}
return absPath, nil
}
// Function to download Mozilla source if not present
func DownloadSource(sourcePath string, sourceRepo string) {
if _, err := os.Stat(sourcePath); os.IsNotExist(err) {
fmt.Println("Mozilla source not found. Cloning from repository...")
if err := runCommand("hg", "clone", sourceRepo, sourcePath); err != nil {
errors = append(errors, "Failed to clone Mozilla repository.")
}
} else {
fmt.Println("Mozilla source already exists.")
}
}
// Function to discard uncommitted changes
func DiscardChanges(sourcePath string) {
fmt.Println("Discarding uncommitted changes...")
if err := runCommand("hg", "revert", "--all", "--no-backup", "-R", sourcePath); err != nil {
errors = append(errors, "Failed to revert changes in Mozilla repository.")
}
}
// Function to clean build
func CleanBuild(sourcePath string) {
fmt.Println("Cleaning build...")
if err := os.Chdir(sourcePath); err != nil {
errors = append(errors, "Failed to navigate to source directory.")
return
}
if err := runCommand("hg", "revert", "--all", "--no-backup"); err != nil {
errors = append(errors, "Failed to revert changes in Mozilla repository.")
}
if err := runCommand("./mach", "clobber"); err != nil {
errors = append(errors, "Failed to clean build.")
}
}
// Function to update Mozilla repository
func UpdateRepo(sourcePath string) {
fmt.Println("Updating Mozilla repository...")
if err := os.Chdir(sourcePath); err != nil {
errors = append(errors, "Failed to navigate to source directory.")
return
}
if err := runCommand("hg", "pull", "-u"); err != nil {
errors = append(errors, "Failed to update Mozilla repository.")
}
}
// Function to update patches
func UpdatePatches(patchesDir, patchesRepo, sourcePath string) {
fmt.Println("Updating patches...")
if _, err := os.Stat(patchesDir); err == nil {
fmt.Println("Patches directory already exists. Cleaning and pulling updates...")
if err := os.Chdir(patchesDir); err != nil {
errors = append(errors, "Failed to navigate to patches directory.")
return
}
if err := runCommand("git", "clean", "-xdf"); err != nil {
errors = append(errors, "Failed to clean patches directory.")
}
_ = runCommand("git", "stash", "push", "--include-untracked")
if err := runCommand("git", "fetch"); err != nil {
errors = append(errors, "Failed to fetch updates from patches repository.")
}
if runCommand("git", "show-ref", "--verify", "--quiet", "refs/heads/main") == nil {
if err := runCommand("git", "rebase", "origin/main"); err != nil {
errors = append(errors, "Failed to rebase updates from main branch.")
}
} else if runCommand("git", "show-ref", "--verify", "--quiet", "refs/heads/master") == nil {
if err := runCommand("git", "rebase", "origin/master"); err != nil {
errors = append(errors, "Failed to rebase updates from master branch.")
}
} else {
errors = append(errors, "No valid branch (main or master) found in patches repository.")
return
}
if runCommand("git", "stash", "list") == nil {
_ = runCommand("git", "stash", "pop")
} else {
fmt.Println("No stash entries found, skipping pop.")
}
} else {
fmt.Println("Patches directory does not exist. Cloning repository...")
if err := runCommand("git", "clone", patchesRepo, patchesDir); err != nil {
errors = append(errors, "Failed to clone patches repository.")
}
}
// Handle platform-specific rsync command
fmt.Println("Copying files from patches directory to Firefox source directory...")
if runtime.GOOS == "windows" {
// Use robocopy for Windows instead of rsync
if err := runCommand("robocopy", patchesDir, sourcePath, "/MIR"); err != nil {
errors = append(errors, "Failed to copy files (Windows robocopy).")
}
} else {
// Use rsync for Unix-like systems
if err := runCommand("rsync", "-av", "--exclude=.git", patchesDir+"/", sourcePath+"/"); err != nil {
errors = append(errors, "Failed to copy files (rsync).")
}
}
}
// Function to configure Spitfire
func Configure(sourcePath string) {
fmt.Println("Configuring Spitfire...")
if err := os.Chdir(sourcePath); err != nil {
errors = append(errors, "Failed to navigate to source directory.")
return
}
if err := runCommand("./mach", "configure"); err != nil {
errors = append(errors, "Configuration failed.")
}
}
// Function to build Spitfire
func Build(sourcePath string) {
fmt.Println("Building Spitfire...")
if err := os.Chdir(sourcePath); err != nil {
errors = append(errors, "Failed to navigate to source directory.")
return
}
if err := runCommand("./mach", "build"); err != nil {
errors = append(errors, "Build failed.")
}
}
// Function to run the project after build
func RunProject(sourcePath string) {
fmt.Println("Running the project...")
if err := os.Chdir(sourcePath); err != nil {
errors = append(errors, "Failed to navigate to source directory.")
return
}
if err := runCommand("./mach", "run"); err != nil {
errors = append(errors, "Failed to run the project.")
}
}
// Function to print collected errors
func PrintErrors() {
if len(errors) > 0 {
fmt.Println("The following errors occurred during execution:")
for _, err := range errors {
fmt.Printf("- %s\n", err)
}
}
}