Compare commits

..

No commits in common. "430357108ce04a77f92fb166d4781fbded35696c" and "89687eecd6a26356873d2c8326852ce90e173ad2" have entirely different histories.

6 changed files with 208 additions and 528 deletions

1
.gitignore vendored
View file

@ -5,4 +5,3 @@
/APKINDEX /APKINDEX
/APPINDEX /APPINDEX
/browser-amd64-nightly-linux.tar.gz /browser-amd64-nightly-linux.tar.gz
/browser-amd64-nightly-windows.tar.gz

145
README.md
View file

@ -1,145 +0,0 @@
<p align="center">
<img src="https://weforge.xyz/Spitfire/Branding/raw/branch/main/active/browser/icon.svg" alt="Logo" width="64" height="64">
</p>
<p align="center" style="font-size: 32px;">
<strong>Spitfire Builder</strong>
</p>
<p align="center">
This is a "simple" script for building the Spitfire Browser based on Mozilla Firefox source code.
</p>
## Dependencies
- Mercurial (hg)
- Git
- Golang (tested with v1.21)
- Python 3.11 and pip3
# Example usage:
## Build:
```sh
go run . -a
```
## Upload:
```sh
go run . --upload -c --upload-path=./mozilla-central/obj-x86_64-pc-linux-gnu/dist/bin
```
## Build and upload:
```sh
go run . --upload -c --upload-path=./mozilla-central/obj-x86_64-pc-linux-gnu/dist/bin -a
```
## Display all flags:
```sh
go run . -h
```
### Config file for uploading example:
*sourceforge_config.json*
```json
{
"SFKeyPath": "~/.ssh/id_rsa.pub",
"SFUser": "internet-addict",
"SFHost": "web.sourceforge.net",
"SFProject": "spitfire-browser"
}
```
## APPINDEX example:
```
C:905cd0cc2dea9e400e1ecd099462b6b19188a9f1
P:Spitfire
R:nightly
V:2024.09.08
A:amd64
S:788506622
I:3324483350
T:Spitfire build
U:https://spitfirebrowser.com/
L:AGPL-3.0
o:browser
m:Internet Addict
t:1725830641
c:905cd0cc2dea9e400e1ecd099462b6b19188a9f1
D:
p:linux
q:
Z:905cd0cc2dea9e400e1ecd099462b6b19188a9f1
```
## Repositary structure
```
spitfire-browser/
├── browser/
│ ├── amd64/
│ │ ├── stable/
│ │ │ ├── latest/deb.tar.gz
│ │ │ ├── x.x.x/deb.tar.gz
│ │ ├── nightly/
│ │ ├── latest/deb.tar.gz
│ │ ├── yyyy-mm-dd/deb.tar.gz
│ ├── arm/
│ │ ├── stable/
│ │ │ ├── latest/
│ │ │ ├── x.x.x/
│ │ ├── nightly/
│ │ ├── latest/
│ │ ├── yyyy-mm-dd/
├── cli-package-manager/
│ ├── stable/
│ │ ├── latest/
│ │ ├── x.x.x/
│ ├── nightly/
│ ├── latest/
│ ├── yyyy-mm-dd/
├── gui-installer/
│ ├── stable/
│ │ ├── latest/
│ │ ├── x.x.x/
│ ├── nightly/
│ ├── latest/
│ ├── yyyy-mm-dd/
├── gui-package-manager/
│ ├── stable/
│ │ ├── latest/
│ │ ├── x.x.x/
│ ├── nightly/
│ ├── latest/
│ ├── yyyy-mm-dd/
├── addons/
│ ├── themes/
│ │ ├── stable/
│ │ │ ├── latest/
│ │ │ ├── x.x.x/
│ │ ├── nightly/
│ │ ├── latest/
│ │ ├── yyyy-mm-dd/
│ ├── custom-configs/
│ │ ├── stable/
│ │ │ ├── latest/
│ │ │ ├── x.x.x/
│ │ ├── nightly/
│ │ ├── latest/
│ │ ├── yyyy-mm-dd/
│ ├── search-engines/
│ ├── stable/
│ │ ├── latest/
│ │ ├── x.x.x/
│ ├── nightly/
│ ├── latest/
│ ├── yyyy-mm-dd/
├── APPINDEX
```

401
main.go
View file

@ -1,254 +1,231 @@
package main package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"runtime" // for detecting system architecture and platform "runtime" // for detecting system architecture and platform
"spitfire/spitfire" "time"
"time" "spitfire/spitfire"
//"errors" //"errors"
) )
var ( var (
// Define all flags as package-level variables // Define all flags as package-level variables
all bool all bool
buildFlag bool buildFlag bool
clean bool clean bool
update bool update bool
patches bool patches bool
run bool run bool
compress bool compress bool
buildPath string buildPath string
target string target string
version string version string
component string component string
arch string arch string
release string release string
platform string platform string
upload bool upload bool
uploadPath string uploadPath string
sourceRepo = "https://hg.mozilla.org/mozilla-central" sourceRepo = "https://hg.mozilla.org/mozilla-central"
patchesRepo = "https://weforgecode.xyz/Spitfire/Browser.git" patchesRepo = "https://weforgecode.xyz/Spitfire/Browser.git"
url = "https://spitfirebrowser.com/" url = "https://spitfirebrowser.com/"
licence = "AGPL-3.0" licence = "AGPL-3.0"
name = "Spitfire" name = "Spitfire"
maintainer = "Internet Addict" maintainer = "Internet Addict"
initialDir string initialDir string
) )
func init() { func init() {
flag.StringVar(&buildPath, "p", "", "Path to the build directory") flag.StringVar(&buildPath, "p", "", "Path to the build directory")
flag.StringVar(&target, "t", "", "Target location format: component-arch-release-platform") 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.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(&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(&component, "component", "browser", "Component name (default: browser)")
flag.StringVar(&arch, "arch", runtime.GOARCH, "Architecture (default: system architecture)") flag.StringVar(&arch, "arch", runtime.GOARCH, "Architecture (default: system architecture)")
flag.StringVar(&release, "release", "nightly", "Release type (default: nightly)") flag.StringVar(&release, "release", "nightly", "Release type (default: nightly)")
flag.StringVar(&platform, "platform", runtime.GOOS, "Platform (default: system platform)") flag.StringVar(&platform, "platform", runtime.GOOS, "Platform (default: system platform)")
flag.BoolVar(&all, "a", false, "Perform all steps (build, clean, update)") flag.BoolVar(&all, "a", false, "Perform all steps (build, clean, update)")
flag.BoolVar(&buildFlag, "b", false, "Build Spitfire") flag.BoolVar(&buildFlag, "b", false, "Build Spitfire")
flag.BoolVar(&clean, "clean", false, "Clean build") flag.BoolVar(&clean, "clean", false, "Clean build")
flag.BoolVar(&update, "u", false, "Update Mozilla repository") flag.BoolVar(&update, "u", false, "Update Mozilla repository")
flag.BoolVar(&patches, "patches", false, "Update patches") flag.BoolVar(&patches, "patches", false, "Update patches")
flag.BoolVar(&run, "r", false, "Run the project after build") flag.BoolVar(&run, "r", false, "Run the project after build")
flag.BoolVar(&upload, "upload", false, "Upload the compressed build file to SourceForge") 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.StringVar(&uploadPath, "upload-path", "", "Path to the file to upload if no build present")
flag.Bool("h", false, "Display help message") flag.Bool("h", false, "Display help message")
} }
func printHelp() { func printHelp() {
fmt.Println("Usage: go run . -p=<path-to-build> -t=<target> [-c|--compress] [-v|--version=<version>] [-component=<component>] [-arch=<architecture>] [-release=<release>] [-platform=<platform>]") fmt.Println("Usage: ./main -p=<path-to-build> -t=<target> [-c|--compress] [-v|--version=<version>] [-component=<component>] [-arch=<architecture>] [-release=<release>] [-platform=<platform>]")
flag.PrintDefaults() flag.PrintDefaults()
fmt.Println("Example: go run . --upload -c --upload-path=./mozilla-central/obj-x86_64-pc-linux-gnu/dist/bin -a") fmt.Println("Example: go run . --upload -c --upload-path=./mozilla-central/obj-x86_64-pc-linux-gnu/dist/bin -a")
os.Exit(0) os.Exit(0)
} }
func main() { func main() {
// // Check system dependencies flag.Parse()
// err := spitfire.CheckSystemDependencies()
// if err != nil {
// log.Fatalf("System check failed: %v", err)
// }
flag.Parse() if flag.Lookup("h").Value.(flag.Getter).Get().(bool) {
printHelp()
}
if flag.Lookup("h").Value.(flag.Getter).Get().(bool) { // Set version to current date if it's empty and release is nightly
printHelp() if version == "" && release == "nightly" {
} version = time.Now().Format("2006.01.02") // Set version to current date if nightly
}
// Set version to current date if it's empty and release is nightly // Save the initial directory
if version == "" && release == "nightly" { var err error
version = time.Now().Format("2006.01.02") // Set version to current date if nightly initialDir, err = os.Getwd()
} if err != nil {
log.Fatalf("Failed to get current working directory: %v", err)
}
fmt.Printf("Initial working directory: %s\n", initialDir)
// Save the initial directory if all || buildFlag {
var err2 error BuildProcess()
initialDir, err2 = os.Getwd() }
if err2 != nil {
log.Fatalf("Failed to get current working directory: %v", err2)
}
fmt.Printf("Initial working directory: %s\n", initialDir)
// Convert buildPath and uploadPath to absolute paths if compress || upload {
if buildPath != "" { PackageAndUploadProcess()
buildPath, err2 = spitfire.ResolvePath(buildPath) }
if err2 != nil {
log.Fatalf("Failed to convert buildPath to absolute path: %v", err2)
}
fmt.Printf("Resolved buildPath: %s\n", buildPath)
}
if uploadPath != "" { spitfire.PrintErrors()
uploadPath, err2 = spitfire.ResolvePath(uploadPath)
if err2 != nil {
log.Fatalf("Failed to convert uploadPath to absolute path: %v", err2)
}
fmt.Printf("Resolved uploadPath: %s\n", uploadPath)
}
if all || buildFlag {
BuildProcess()
}
if compress || upload {
PackageAndUploadProcess()
}
spitfire.PrintErrors()
} }
// BuildProcess handles the build process: downloading, cleaning, configuring, and building the project. // BuildProcess handles the build process: downloading, cleaning, configuring, and building the project.
func BuildProcess() { func BuildProcess() {
sourcePath, err := spitfire.ResolvePath("./mozilla-central") sourcePath, err := spitfire.ResolvePath("./mozilla-central")
if err != nil { if err != nil {
log.Fatalf("Error resolving source path: %v", err) log.Fatalf("Error resolving source path: %v", err)
} }
patchesDir, err := spitfire.ResolvePath(filepath.Join(sourcePath, "Spitfire")) patchesDir, err := spitfire.ResolvePath(filepath.Join(sourcePath, "Spitfire"))
if err != nil { if err != nil {
log.Fatalf("Error resolving patches directory: %v", err) log.Fatalf("Error resolving patches directory: %v", err)
} }
if all { if all {
spitfire.DownloadSource(sourcePath, sourceRepo) spitfire.DownloadSource(sourcePath, sourceRepo)
spitfire.DiscardChanges(sourcePath) spitfire.DiscardChanges(sourcePath)
spitfire.CleanBuild(sourcePath) spitfire.CleanBuild(sourcePath)
spitfire.UpdateRepo(sourcePath) spitfire.UpdateRepo(sourcePath)
spitfire.UpdatePatches(patchesDir, patchesRepo, sourcePath) spitfire.UpdatePatches(patchesDir, patchesRepo, sourcePath)
spitfire.Configure(sourcePath) spitfire.Configure(sourcePath)
spitfire.Build(sourcePath) spitfire.Build(sourcePath)
if run { if run {
spitfire.RunProject(sourcePath) spitfire.RunProject(sourcePath)
} }
fmt.Println("Spitfire build completed successfully.") fmt.Println("Spitfire build completed successfully.")
} else if clean { } else if clean {
spitfire.CleanBuild(sourcePath) spitfire.CleanBuild(sourcePath)
fmt.Println("Cleaned Firefox build.") fmt.Println("Cleaned Firefox build.")
} else if update { } else if update {
spitfire.DownloadSource(sourcePath, sourceRepo) spitfire.DownloadSource(sourcePath, sourceRepo)
spitfire.UpdateRepo(sourcePath) spitfire.UpdateRepo(sourcePath)
fmt.Println("Mozilla repository updated.") fmt.Println("Mozilla repository updated.")
} else if patches { } else if patches {
spitfire.DownloadSource(sourcePath, sourceRepo) spitfire.DownloadSource(sourcePath, sourceRepo)
spitfire.UpdatePatches(patchesDir, patchesRepo, sourcePath) spitfire.UpdatePatches(patchesDir, patchesRepo, sourcePath)
fmt.Println("Patches updated.") fmt.Println("Patches updated.")
} else if buildFlag { } else if buildFlag {
spitfire.Configure(sourcePath) spitfire.Configure(sourcePath)
spitfire.Build(sourcePath) spitfire.Build(sourcePath)
if run { if run {
spitfire.RunProject(sourcePath) spitfire.RunProject(sourcePath)
} }
fmt.Println("Spitfire build completed successfully.") fmt.Println("Spitfire build completed successfully.")
} }
} }
// PackageAndUploadProcess handles compressing, packaging, and uploading the build to SourceForge. // PackageAndUploadProcess handles compressing, packaging, and uploading the build to SourceForge.
func PackageAndUploadProcess() { func PackageAndUploadProcess() {
// Restore working directory before performing SourceForge operations // Restore working directory before performing SourceForge operations
restoreWorkingDirectory() restoreWorkingDirectory()
pathToUse := buildPath pathToUse := buildPath
if upload && uploadPath != "" { if upload && uploadPath != "" {
pathToUse = uploadPath pathToUse = uploadPath
} }
if pathToUse == "" { if pathToUse == "" {
log.Fatalf("Error: no valid build or upload path provided.") log.Fatalf("Error: no valid build or upload path provided.")
} }
// // This is stupid, it wait for the path to exist (up to a maximum wait time) // // This is stupid, it wait for the path to exist (up to a maximum wait time)
// err := waitForPath(pathToUse, 60, 5) // Max 60 seconds, checking every 5 seconds // err := waitForPath(pathToUse, 60, 5) // Max 60 seconds, checking every 5 seconds
// if err != nil { // if err != nil {
// log.Fatalf("Error: Build path or upload path not found: %v", err) // log.Fatalf("Error: Build path or upload path not found: %v", err)
// } // }
uncompressedSize, err := spitfire.GetDirectorySize(pathToUse) uncompressedSize, err := spitfire.GetDirectorySize(pathToUse)
if err != nil { if err != nil {
log.Fatalf("Failed to calculate uncompressed size: %v", err) log.Fatalf("Failed to calculate uncompressed size: %v", err)
} }
fmt.Printf("Uncompressed directory size: %d bytes\n", uncompressedSize) fmt.Printf("Uncompressed directory size: %d bytes\n", uncompressedSize)
outputCompressedFile := filepath.Join(".", fmt.Sprintf("%s-%s-%s-%s.tar.gz", component, arch, release, platform)) outputCompressedFile := filepath.Join(".", fmt.Sprintf("%s-%s-%s-%s.tar.gz", component, arch, release, platform))
if compress { if compress {
err := spitfire.CompressDirectory(pathToUse, outputCompressedFile) err := spitfire.CompressDirectory(pathToUse, outputCompressedFile)
if err != nil { if err != nil {
log.Fatalf("Failed to compress build directory: %v", err) log.Fatalf("Failed to compress build directory: %v", err)
} }
fmt.Printf("Build directory compressed to: %s\n", outputCompressedFile) fmt.Printf("Build directory compressed to: %s\n", outputCompressedFile)
} }
compressedSize, err := spitfire.GetFileSize(outputCompressedFile) compressedSize, err := spitfire.GetFileSize(outputCompressedFile)
if err != nil { if err != nil {
log.Fatalf("Failed to get compressed file size: %v", err) log.Fatalf("Failed to get compressed file size: %v", err)
} }
fmt.Printf("Compressed file size: %d bytes\n", compressedSize) fmt.Printf("Compressed file size: %d bytes\n", compressedSize)
if upload { if upload {
config, err := spitfire.LoadConfig() config, err := spitfire.LoadConfig()
if err != nil { if err != nil {
log.Fatalf("Failed to load SourceForge config: %v", err) log.Fatalf("Failed to load SourceForge config: %v", err)
} }
if _, err := os.Stat(outputCompressedFile); err == nil { if _, err := os.Stat(outputCompressedFile); err == nil {
err = spitfire.Upload(config, outputCompressedFile, "/home/frs/project/spitfire-browser/"+component+"/"+arch+"/"+release+"/"+version+"/") err = spitfire.Upload(config, outputCompressedFile, "/home/frs/project/spitfire-browser/"+component+"/"+arch+"/"+release+"/"+version+"/")
if err != nil { if err != nil {
log.Fatalf("Failed to upload compressed file: %v", err) log.Fatalf("Failed to upload compressed file: %v", err)
} }
fmt.Println("Compressed file uploaded successfully.") fmt.Println("Compressed file uploaded successfully.")
} else { } else {
log.Fatalf("No compressed file found to upload.") log.Fatalf("No compressed file found to upload.")
} }
err = spitfire.DownloadAPPINDEX(config, "/home/frs/project/spitfire-browser/") err = spitfire.DownloadAPPINDEX(config, "/home/frs/project/spitfire-browser/")
if err != nil { if err != nil {
fmt.Println("Failed to download APPINDEX. A new APPINDEX will be created and uploaded.") fmt.Println("Failed to download APPINDEX. A new APPINDEX will be created and uploaded.")
} }
err = spitfire.PackageAPPINDEX( err = spitfire.PackageAPPINDEX(
name, release, version, arch, name, release, version, arch,
fmt.Sprintf("%d", compressedSize), fmt.Sprintf("%d", compressedSize),
fmt.Sprintf("%d", uncompressedSize), fmt.Sprintf("%d", uncompressedSize),
"Spitfire build", url, licence, component, maintainer, "", platform, "Spitfire build", url, licence, component, maintainer, "", platform,
) )
if err != nil { if err != nil {
log.Fatalf("Failed to update APPINDEX: %v", err) log.Fatalf("Failed to update APPINDEX: %v", err)
} }
fmt.Println("APPINDEX updated successfully.") fmt.Println("APPINDEX updated successfully.")
if err := spitfire.CleanAppIndex(); err != nil { if err := spitfire.CleanAppIndex(); err != nil {
log.Fatalf("Failed to clean APPINDEX: %v", err) log.Fatalf("Failed to clean APPINDEX: %v", err)
} }
err = spitfire.UploadAPPINDEX(config, "/home/frs/project/spitfire-browser/") err = spitfire.UploadAPPINDEX(config, "/home/frs/project/spitfire-browser/")
if err != nil { if err != nil {
log.Fatalf("Failed to upload updated APPINDEX: %v", err) log.Fatalf("Failed to upload updated APPINDEX: %v", err)
} }
fmt.Println("APPINDEX uploaded successfully.") fmt.Println("APPINDEX uploaded successfully.")
} }
} }
// // waitForPath checks if a path exists, waiting for up to maxWait seconds and retrying every interval seconds. // // waitForPath checks if a path exists, waiting for up to maxWait seconds and retrying every interval seconds.
@ -275,9 +252,9 @@ func PackageAndUploadProcess() {
// restoreWorkingDirectory restores the initial working directory after any operation that might change it. // restoreWorkingDirectory restores the initial working directory after any operation that might change it.
func restoreWorkingDirectory() { func restoreWorkingDirectory() {
err := os.Chdir(initialDir) err := os.Chdir(initialDir)
if err != nil { if err != nil {
log.Fatalf("Failed to restore the working directory: %v", err) log.Fatalf("Failed to restore the working directory: %v", err)
} }
fmt.Printf("Restored working directory to: %s\n", initialDir) fmt.Printf("Restored working directory to: %s\n", initialDir)
} }

View file

@ -1,6 +1,7 @@
{ {
"SFKeyPath": "~/.ssh/id_rsa.pub", "SFKeyPath": "~/.ssh/id_rsa.pub",
"SFUser": "internet-addict", "SFUser": "internet-addict",
"SFHost": "web.sourceforge.net", "SFHost": "web.sourceforge.net",
"SFProject": "spitfire-browser" "SFProject": "spitfire-browser"
} }

View file

@ -5,39 +5,13 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime"
) )
// Array to store errors // Array to store errors
var errors []string var errors []string
// SetGlobalEnv sets the MOZILLABUILD environment variable globally for the user (or system)
func SetGlobalEnv(variable, value string, scope string) error {
if runtime.GOOS == "windows" {
var cmd *exec.Cmd
if scope == "user" {
cmd = exec.Command("setx", variable, value) // Set for current user
} else if scope == "system" {
cmd = exec.Command("setx", variable, value, "/M") // Set for system (requires admin privileges)
} else {
return fmt.Errorf("unknown scope: %s", scope)
}
// Run the command
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to set environment variable %s=%s: %v\nOutput: %s", variable, value, err, string(out))
}
fmt.Printf("Successfully set %s=%s\n", variable, value)
return nil
} else {
return fmt.Errorf("global environment variable setting is not supported on non-Windows systems")
}
}
// Run an external command like scp or rsync // Run an external command like scp or rsync
func runCommand(command string, args ...string) error { func runCommand(command string, args ...string) error {
fmt.Printf("Running command: %s %v\n", command, args)
cmd := exec.Command(command, args...) cmd := exec.Command(command, args...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@ -46,13 +20,9 @@ func runCommand(command string, args ...string) error {
// Function to resolve paths using absolute path // Function to resolve paths using absolute path
func ResolvePath(path string) (string, error) { 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) absPath, err := filepath.Abs(path)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to resolve path: %s, error: %v", path, err) return "", fmt.Errorf("failed to resolve path: %s", path)
} }
return absPath, nil return absPath, nil
} }
@ -84,21 +54,10 @@ func CleanBuild(sourcePath string) {
errors = append(errors, "Failed to navigate to source directory.") errors = append(errors, "Failed to navigate to source directory.")
return return
} }
// Use the appropriate mach command for Windows or Unix-like systems
var machCmd string
if runtime.GOOS == "windows" {
machCmd = ".\\mach"
} else {
machCmd = "./mach"
}
// Revert uncommitted changes
if err := runCommand("hg", "revert", "--all", "--no-backup"); err != nil { if err := runCommand("hg", "revert", "--all", "--no-backup"); err != nil {
errors = append(errors, "Failed to revert changes in Mozilla repository.") errors = append(errors, "Failed to revert changes in Mozilla repository.")
} }
// Clean the build if err := runCommand("./mach", "clobber"); err != nil {
if err := runCommand(machCmd, "clobber"); err != nil {
errors = append(errors, "Failed to clean build.") errors = append(errors, "Failed to clean build.")
} }
} }
@ -154,19 +113,9 @@ func UpdatePatches(patchesDir, patchesRepo, sourcePath string) {
errors = append(errors, "Failed to clone patches repository.") errors = append(errors, "Failed to clone patches repository.")
} }
} }
// Handle platform-specific rsync command
fmt.Println("Copying files from patches directory to Firefox source directory...") fmt.Println("Copying files from patches directory to Firefox source directory...")
if runtime.GOOS == "windows" { if err := runCommand("rsync", "-av", "--exclude=.git", patchesDir+"/", sourcePath+"/"); err != nil {
// Use robocopy for Windows errors = append(errors, "Failed to copy files.")
if err := runCommand("robocopy", patchesDir, sourcePath, "*", "/S", "/XF", ".git", "/XD", ".git"); 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).")
}
} }
} }
@ -177,16 +126,7 @@ func Configure(sourcePath string) {
errors = append(errors, "Failed to navigate to source directory.") errors = append(errors, "Failed to navigate to source directory.")
return return
} }
if err := runCommand("./mach", "configure"); err != nil {
// Use the appropriate mach command for Windows or Unix-like systems
var machCmd string
if runtime.GOOS == "windows" {
machCmd = ".\\mach"
} else {
machCmd = "./mach"
}
if err := runCommand(machCmd, "configure"); err != nil {
errors = append(errors, "Configuration failed.") errors = append(errors, "Configuration failed.")
} }
} }
@ -198,16 +138,7 @@ func Build(sourcePath string) {
errors = append(errors, "Failed to navigate to source directory.") errors = append(errors, "Failed to navigate to source directory.")
return return
} }
if err := runCommand("./mach", "build"); err != nil {
// Use the appropriate mach command for Windows or Unix-like systems
var machCmd string
if runtime.GOOS == "windows" {
machCmd = ".\\mach"
} else {
machCmd = "./mach"
}
if err := runCommand(machCmd, "build"); err != nil {
errors = append(errors, "Build failed.") errors = append(errors, "Build failed.")
} }
} }
@ -215,16 +146,11 @@ func Build(sourcePath string) {
// Function to run the project after build // Function to run the project after build
func RunProject(sourcePath string) { func RunProject(sourcePath string) {
fmt.Println("Running the project...") fmt.Println("Running the project...")
if err := os.Chdir(sourcePath); err != nil {
// Use the appropriate mach command for Windows or Unix-like systems errors = append(errors, "Failed to navigate to source directory.")
var machCmd string return
if runtime.GOOS == "windows" {
machCmd = ".\\mach"
} else {
machCmd = "./mach"
} }
if err := runCommand("./mach", "run"); err != nil {
if err := runCommand(machCmd, "run"); err != nil {
errors = append(errors, "Failed to run the project.") errors = append(errors, "Failed to run the project.")
} }
} }

View file

@ -1,78 +0,0 @@
package spitfire
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
)
// CheckSystemDependencies ensures that required tools for building are installed.
func CheckSystemDependencies() error {
requiredTools := map[string]string{
"git": "https://git-scm.com/download/win", // Git
"python": "https://www.python.org/downloads/", // Python
"pip3": "https://pip.pypa.io/en/stable/installing/", // Pip3
}
if runtime.GOOS == "windows" {
// Check for MozillaBuild installation
mozBuildPath := os.Getenv("MOZILLABUILD")
if mozBuildPath == "" {
mozBuildPath = "C:\\mozilla-build" // Default to standard MozillaBuild path
}
// Check if MozillaBuild exists at the specified location
if !dirExists(mozBuildPath) {
requiredTools["mozbuild"] = "https://ftp.mozilla.org/pub/mozilla/libraries/win32/MozillaBuildSetup-Latest.exe"
}
}
missingTools := []string{}
// Check for each required tool
for tool, downloadLink := range requiredTools {
if !isCommandAvailable(tool) {
missingTools = append(missingTools, fmt.Sprintf("%s (Download: %s)", tool, downloadLink))
}
}
// Special check for mach in the local source directory (mozilla-central)
machPath := filepath.Join("mozilla-central", "mach")
if !fileExists(machPath) {
missingTools = append(missingTools, fmt.Sprintf("mach (run from mozilla-central directory)"))
}
if len(missingTools) > 0 {
fmt.Println("The following tools are missing and are required for the build:")
for _, tool := range missingTools {
fmt.Println(" - " + tool)
}
return fmt.Errorf("missing required tools")
}
fmt.Println("All required system dependencies are installed.")
return nil
}
// isCommandAvailable checks if a command/tool is available on the system.
func isCommandAvailable(command string) bool {
_, err := exec.LookPath(command)
return err == nil
}
// fileExists checks if a file exists at the given path.
func fileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
// dirExists checks if a directory exists at the given path.
func dirExists(path string) bool {
info, err := os.Stat(path)
if os.IsNotExist(err) {
return false
}
return info.IsDir()
}