From 50526b78aa69ec104c5037fa58091d215810ed38 Mon Sep 17 00:00:00 2001 From: Evan Burkey Date: Mon, 16 Jun 2025 13:53:06 -0700 Subject: [PATCH] remove native UI elements, update README --- .gitignore | 1 + README.md | 7 ++++--- config.go | 5 ++++- main.go | 55 +++++++++++++++++++++++++++++++----------------------- release.sh | 18 +++++++++++------- 5 files changed, 52 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 8d9f9bf..8ce0576 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea bin/ epochcli-* +epochcli *.tar.gz diff --git a/README.md b/README.md index df012cf..c7b5513 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,11 @@ CLI tool for updating and launching [Project Epoch](https://www.project-epoch.net/) on Linux & macOS. ## Setup -For Linux, a `wine` prefix with `dxvk` installed is sufficient, or you can use something like Lutris or faugus-launcher without the launcher functionality in `epochcli` +For Linux, a `wine` prefix with `dxvk` installed is sufficient, or you can use something like Lutris or faugus-launcher without the launcher functionality in `epochcli`. -For macOS, the [Kegworks Wineskin port](https://github.com/Kegworks-App/Kegworks) works great (tutorial coming in the future...) +For macOS, I've found the best way to run the client is in a Parallels Win 11 VM. Kegworks, Codeweavers, etc crash when the game starts up and I have not found a good solution so far. -1. Download and extract the latest binary from the [releases](https://git.burkey.co/eburk/epochcli/releases) page. Due to using OS UI code, `epochcli` cannot be cross-compiled. I only provide release builds for the hardware I own (Linux amd64, macOS arm64). If you need a different platform, you will need to compile yourself. You can run `go install git.burkey.co/eburk/epochcli` to compile and install to your `$GOROOT` +1. Download and extract the latest binary from the [releases](https://git.burkey.co/eburk/epochcli/releases) page. 2. Run `epochcli`. You will be taken through a setup process that configures the program and creates a config file at `$HOME/.config/epochcli/config.toml` 3. You can now use `epochcli` as just a standalone updater or also a launcher based on your configuration. You can always run `epochcli -c` to redo the configuration or edit the config file manually @@ -15,6 +15,7 @@ For macOS, the [Kegworks Wineskin port](https://github.com/Kegworks-App/Kegworks ``` > ./epochcli -h -c Runs config configuration step. Overrides the config file + -f Forces epochcli to update files even if they match the current version -h Print help -u Ignore EnableLauncher setting in config and only runs an update. Does nothing if EnableLauncher is false ``` diff --git a/config.go b/config.go index f00afc8..aaf7e89 100644 --- a/config.go +++ b/config.go @@ -37,7 +37,10 @@ func setupConfig(rerun bool) (*Config, error) { _, statErr := os.Stat(cfgPath) if rerun || os.IsNotExist(statErr) { fmt.Println("Enter the path to your Wow directory below:") - fmt.Scanln(&newConfig.WowDir) + _, err := fmt.Scanln(&newConfig.WowDir) + if err != nil { + return nil, err + } for { fmt.Printf("Do you want to use epochcli to launch Wow? Select No if you plan on using a launcher tool like Lutris (y/n): ") diff --git a/main.go b/main.go index cdfbd89..b2fff96 100644 --- a/main.go +++ b/main.go @@ -25,9 +25,11 @@ func main() { var ( helpFlag bool updateOnlyFlag bool + forceFlag bool rerunConfig bool ) flag.BoolVar(&helpFlag, "h", false, "Print help") + flag.BoolVar(&forceFlag, "f", false, "Forces epochcli to update files even if they match the current version") flag.BoolVar(&updateOnlyFlag, "u", false, "Ignore EnableLauncher setting in config and only runs an update. Does nothing if EnableLauncher is false") flag.BoolVar(&rerunConfig, "c", false, "Runs config configuration step. Overrides the config file") flag.Parse() @@ -47,14 +49,14 @@ func main() { log.Fatalf("WowDir in %s is still the default setting, exiting", cfgPath) } - updated, current, err := downloadUpdate(config) + stats, err := downloadUpdate(config, forceFlag) if err != nil { log.Fatal(err) } - fmt.Printf("Updated %d files\n", updated) - if current > 0 { - fmt.Printf("%d files are already up to date\n", current) + fmt.Printf("%d files updated\n", stats.updated) + if stats.current > 0 { + fmt.Printf("%d files are already up to date\n", stats.current) } if updateOnlyFlag { @@ -76,8 +78,13 @@ func main() { } } -func downloadUpdate(config *Config) (int, int, error) { - var updateCount, currentCount int +type DownloadStats struct { + updated int + current int +} + +func downloadUpdate(config *Config, force bool) (DownloadStats, error) { + var stats DownloadStats manifest, err := getManifest() if err != nil { @@ -94,17 +101,19 @@ func downloadUpdate(config *Config) (int, int, error) { os.MkdirAll(localDir, 0755) } - if _, err = os.Stat(localPath); err == nil { - data, err := os.ReadFile(localPath) - if err != nil { - return updateCount, currentCount, err - } - hashBytes := md5.Sum(data) - hash := hex.EncodeToString(hashBytes[:]) - if hash == file.Hash { - fmt.Printf("File %s is up to date\n", localPath) - currentCount += 1 - continue + if !force { + if _, err = os.Stat(localPath); err == nil { + data, err := os.ReadFile(localPath) + if err != nil { + return stats, err + } + hashBytes := md5.Sum(data) + hash := hex.EncodeToString(hashBytes[:]) + if hash == file.Hash { + fmt.Printf("File %s is up to date\n", localPath) + stats.current += 1 + continue + } } } @@ -112,26 +121,26 @@ func downloadUpdate(config *Config) (int, int, error) { outFile, err := os.Create(localPath) if err != nil { - return updateCount, currentCount, err + return stats, err } defer outFile.Close() resp, err := http.Get(file.URL) if err != nil { - return updateCount, currentCount, err + return stats, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return updateCount, currentCount, fmt.Errorf("failed to download update from %s, status code: %d", file.URL, resp.StatusCode) + return stats, fmt.Errorf("failed to download update from %s, status code: %d", file.URL, resp.StatusCode) } _, err = io.Copy(outFile, resp.Body) if err != nil { - return updateCount, currentCount, err + return stats, err } - updateCount += 1 + stats.updated += 1 } - return updateCount, currentCount, nil + return stats, nil } diff --git a/release.sh b/release.sh index a37565e..0a00bff 100755 --- a/release.sh +++ b/release.sh @@ -7,12 +7,16 @@ rm -rf bin mkdir bin -if [[ "$OSTYPE" == "linux-gnu"* ]]; then - GOOS=linux GOARCH=amd64 go build -o bin/epochcli-linux-amd64 - tar czvf epochcli-linux-amd64.tar.gz bin/epochcli-linux-amd64 -elif [[ "$OSTYPE" == "darwin"* ]]; then - GOOS=darwin GOARCH=arm64 go build -o bin/epochcli-darwin-arm64 - tar czvf epochcli-darwin-arm64.tar.gz bin/epochcli-darwin-arm64 -fi +GOOS=linux GOARCH=amd64 go build -o bin/epochcli-linux-amd64 +tar czvf epochcli-linux-amd64.tar.gz bin/epochcli-linux-amd64 + +GOOS=linux GOARCH=arm64 go build -o bin/epochcli-linux-arm64 +tar czvf epochcli-linux-arm64.tar.gz bin/epochcli-linux-arm64 + +GOOS=darwin GOARCH=arm64 go build -o bin/epochcli-darwin-arm64 +tar czvf epochcli-darwin-arm64.tar.gz bin/epochcli-darwin-arm64 + +GOOS=darwin GOARCH=amd64 go build -o bin/epochcli-darwin-amd64 +tar czvf epochcli-darwin-amd64.tar.gz bin/epochcli-darwin-amd64 rm -rf bin \ No newline at end of file