Compare commits
	
		
			24 Commits
		
	
	
		
			0.0.1
			...
			a9367763f3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a9367763f3 | |||
| 7dd915b060 | |||
| 4e78277f99 | |||
| ad97817e80 | |||
| 9a0606ce32 | |||
| d4f841f8a0 | |||
| 134d70e29b | |||
| 6199f0865e | |||
| a24eb6903f | |||
| 1fc00d83eb | |||
| 50526b78aa | |||
| 656109e935 | |||
| a281948d0b | |||
| ec7e63ed16 | |||
| 72f7a1e163 | |||
| bdf8067bdc | |||
| 3fab12d6f5 | |||
| 013b8c479f | |||
| 1a6af606ff | |||
| 95d54ea91a | |||
| 235fae8ec9 | |||
| 027a8e073b | |||
| 58f3977707 | |||
| 203449fbf9 | 
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +1,5 @@ | ||||
| .idea | ||||
| epoch-linux | ||||
| bin/ | ||||
| epochcli-* | ||||
| epochcli | ||||
| *.tar.gz | ||||
|   | ||||
							
								
								
									
										16
									
								
								Formula/epochcli.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Formula/epochcli.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| class Epochcli < Formula | ||||
|   desc "Updater and Launcher for Epoch" | ||||
|   homepage "https://git.burkey.co/eburk/epochcli/src/branch/master" | ||||
|   license "ISC" | ||||
|   head "https://git.burkey.co/eburk/epochcli.git", branch: "master" | ||||
|  | ||||
|   depends_on "go" => :build | ||||
|  | ||||
|   def install | ||||
|     system "go", "build", *std_go_args(ldflags: "-s -w") | ||||
|   end | ||||
|  | ||||
|   test do | ||||
|     assert_match "Epochcli Help:", shell_output("#{bin}/epochcli -h") | ||||
|   end | ||||
| end | ||||
							
								
								
									
										52
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,18 +1,46 @@ | ||||
| # epoch-linux | ||||
| # epochcli | ||||
|  | ||||
| Linux updater and launcher for [Project Epoch](https://www.project-epoch.net/)  | ||||
| CLI tool for updating and launching [Project Epoch](https://www.project-epoch.net/) on Windows, Linux and macOS. | ||||
|  | ||||
| ## Instructions | ||||
| ## Installing | ||||
|  | ||||
| 1. Set up a copy of WoW 3.3.5 in a wine prefix or launcher of your choice. Chromiecraft has a good torrent you can use for the 3.3.5 client | ||||
| 2. Install `epoch-linux` by either | ||||
|    1. Download the latest binary from the [releases](https://git.burkey.co/eburk/epoch-linux/releases) page  | ||||
|    2. If you have the `go` toolchain installed, you can run `go get git.burkey.co/eburk/epoch-linux@latest` to install to your `$GOROOT` | ||||
|    3. Compile the source yourself | ||||
| 3. Run `epoch-linux` once. This will create a config file at `$HOME/.config/epoch-linux/config.toml`. Change the `WowDir` variable to your Wow game directory | ||||
| 4. Run `epoch-linux` again. It will download the patch files from Epoch's servers to your Wow directory | ||||
| 5. Use your launcher or tool of choice to startup Epoch in `wine` | ||||
| ### Linux | ||||
| A `wine` prefix with `dxvk` installed is sufficient, or you can use something like Lutris or faugus-launcher and just use `epochcli` for updating. | ||||
|  | ||||
| Download and extract the latest binary from the [releases](https://git.burkey.co/eburk/epochcli/releases) page, build from source yourself, or use homebrew from the macOS instructions to install. | ||||
|  | ||||
| ### macOS | ||||
|  | ||||
| For macOS, I've found the best way to run Wow 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. Any suggestions would be welcome, see my contact information below. I currently use a Parallels VM and run the Windows version of epochcli inside the VM as an updater and launcher. | ||||
|  | ||||
| You can easily install with homebrew or build from source yourself. I dont have time to setup codesigning right now so there are no binaries provided for macOS. For homebrew, do the following: | ||||
|  | ||||
| ```shell | ||||
| brew tap eburk/epochcli https://git.burkey.co/eburk/epochcli | ||||
| brew install --HEAD epochcli | ||||
|  | ||||
| # To update | ||||
| brew upgrade epochcli --fetch-HEAD | ||||
| ``` | ||||
|  | ||||
| ### Windows | ||||
|  | ||||
| Download and extract the latest binary from the [releases](https://git.burkey.co/eburk/epochcli/releases) page or build from source yourself, then copy `epochcli.exe` to a location of your choice. To make it easy, just use the same folder as your Wow game files. | ||||
|  | ||||
| ## Setup | ||||
|  | ||||
| 1. 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` | ||||
| 2. You can now use `epochcli` as a standalone updater, but it can also act as a launcher based on your configuration. You can always run `epochcli -c` to redo the configuration, or edit the config file manually | ||||
|  | ||||
| ## Usage | ||||
| ``` | ||||
| > ./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 | ||||
| ``` | ||||
|  | ||||
| ## Issues | ||||
|  | ||||
| If you have any issues, [email me](mailto:evan@burkey.co) or ping `Battlehammer` on the Epoch discord | ||||
| If you have any issues, [email me](mailto:epochcli@burkey.co) or send a private message to `Battlehammer` on the Epoch discord | ||||
							
								
								
									
										128
									
								
								config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								config.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/BurntSushi/toml" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type Config struct { | ||||
| 	WowDir         string | ||||
| 	LaunchCmd      string | ||||
| 	EnableLauncher bool | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	configDirName = "epochcli" | ||||
| 	configName    = "config.toml" | ||||
| ) | ||||
|  | ||||
| var cfgPath string | ||||
|  | ||||
| func setupConfig(rerun bool) (*Config, error) { | ||||
| 	home, err := os.UserHomeDir() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("unable to determine home directory: %v", err) | ||||
| 	} | ||||
| 	cfgPath = filepath.Join(home, ".config", configDirName, configName) | ||||
|  | ||||
| 	newConfig := Config{ | ||||
| 		WowDir:         defaultWowPath, | ||||
| 		LaunchCmd:      defaultLaunchCmd, | ||||
| 		EnableLauncher: false, | ||||
| 	} | ||||
|  | ||||
| 	_, statErr := os.Stat(cfgPath) | ||||
| 	if rerun || os.IsNotExist(statErr) { | ||||
| 		fmt.Println("Enter the path to your Wow directory below:") | ||||
| 		var s string | ||||
| 		_, err = fmt.Scanln(&s) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("unable to read input: %v", err) | ||||
| 		} | ||||
| 		newConfig.WowDir = strings.TrimSpace(s) | ||||
|  | ||||
| 		p, err := promptYesNo(fmt.Sprintf("Do you want to use epochcli to launch Wow? Select No if you plan on using a launcher tool like Lutris (y/n): ")) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if p { | ||||
| 			newConfig.EnableLauncher = true | ||||
|  | ||||
| 			if runtime.GOOS == "windows" { | ||||
| 				newConfig.LaunchCmd = path.Join(newConfig.WowDir, "Project-Epoch.exe") | ||||
| 				exePath, err := os.Executable() | ||||
| 				if err != nil { | ||||
| 					return nil, fmt.Errorf("unable to create desktop shortcut: %v", err) | ||||
| 				} | ||||
| 				err = makeLink(exePath, path.Join(home, "Desktop", "Project-Epoch.lnk")) | ||||
| 				if err != nil { | ||||
| 					return nil, fmt.Errorf("unable to create desktop shortcut: %v", err) | ||||
| 				} | ||||
| 			} else { | ||||
| 				fmt.Println("Enter your launch command to start Wow below. If you would rather configure this later in the configuration file, just press Enter") | ||||
| 				fmt.Printf("> ") | ||||
|  | ||||
| 				_, err = fmt.Scanf("%s", &s) | ||||
| 				if err != nil { | ||||
| 					return nil, fmt.Errorf("unable to read input: %v", err) | ||||
| 				} | ||||
| 				s = strings.TrimSpace(s) | ||||
|  | ||||
| 				if s != "" { | ||||
| 					newConfig.LaunchCmd = s | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		err = os.MkdirAll(filepath.Join(home, ".config", configDirName), 0755) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("unable to create config directory: %v", err) | ||||
| 		} | ||||
|  | ||||
| 		file, err := os.Create(cfgPath) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("unable to create config file: %v", err) | ||||
| 		} | ||||
| 		defer file.Close() | ||||
|  | ||||
| 		encoder := toml.NewEncoder(file) | ||||
| 		if err = encoder.Encode(newConfig); err != nil { | ||||
| 			return nil, fmt.Errorf("unable to encode config file: %v", err) | ||||
| 		} | ||||
|  | ||||
| 		fmt.Println("Created new config at ", cfgPath) | ||||
| 	} | ||||
|  | ||||
| 	_, err = toml.DecodeFile(cfgPath, &newConfig) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return &newConfig, nil | ||||
| } | ||||
|  | ||||
| func promptYesNo(prompt string) (bool, error) { | ||||
| 	var s string | ||||
| 	for { | ||||
| 		fmt.Print(prompt) | ||||
| 		_, err := fmt.Scanf("%s", &s) | ||||
| 		if err != nil { | ||||
| 			return false, fmt.Errorf("unable to read input: %v", err) | ||||
| 		} | ||||
| 		s := strings.TrimSpace(s) | ||||
|  | ||||
| 		if s == "y" || s == "Y" { | ||||
| 			return true, nil | ||||
| 		} | ||||
|  | ||||
| 		if s == "n" || s == "N" { | ||||
| 			return false, nil | ||||
| 		} | ||||
| 		fmt.Println("Please enter a valid value of either 'y' or 'n'") | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										8
									
								
								config_unix.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								config_unix.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| //go:build linux || darwin | ||||
|  | ||||
| package main | ||||
|  | ||||
| func makeLink(src, dst string) error { | ||||
| 	// Noop on unix | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										36
									
								
								config_windows.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								config_windows.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"github.com/go-ole/go-ole" | ||||
| 	"github.com/go-ole/go-ole/oleutil" | ||||
| 	"runtime" | ||||
| ) | ||||
|  | ||||
| func makeLink(src, dst string) error { | ||||
| 	runtime.LockOSThread() | ||||
| 	defer runtime.UnlockOSThread() | ||||
|  | ||||
| 	err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_SPEED_OVER_MEMORY) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	oleShellObject, err := oleutil.CreateObject("WScript.Shell") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer oleShellObject.Release() | ||||
| 	wshell, err := oleShellObject.QueryInterface(ole.IID_IDispatch) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer wshell.Release() | ||||
| 	cs, err := oleutil.CallMethod(wshell, "CreateShortcut", dst) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	idispatch := cs.ToIDispatch() | ||||
| 	oleutil.PutProperty(idispatch, "TargetPath", src) | ||||
| 	oleutil.CallMethod(idispatch, "Save") | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										9
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
									
									
									
									
								
							| @@ -1,5 +1,10 @@ | ||||
| module git.burkey.co/eburk/epoch-linux | ||||
| module git.burkey.co/eburk/epochcli | ||||
|  | ||||
| go 1.24.3 | ||||
|  | ||||
| require github.com/BurntSushi/toml v1.5.0 | ||||
| require ( | ||||
| 	github.com/BurntSushi/toml v1.5.0 | ||||
| 	github.com/go-ole/go-ole v1.3.0 | ||||
| ) | ||||
|  | ||||
| require golang.org/x/sys v0.1.0 // indirect | ||||
|   | ||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @@ -1,2 +1,6 @@ | ||||
| github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= | ||||
| github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= | ||||
| github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= | ||||
| github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= | ||||
| golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= | ||||
| golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
|   | ||||
							
								
								
									
										147
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								main.go
									
									
									
									
									
								
							| @@ -3,79 +3,88 @@ package main | ||||
| import ( | ||||
| 	"crypto/md5" | ||||
| 	"encoding/hex" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"github.com/BurntSushi/toml" | ||||
| 	"io" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	manifestUrl   = "https://updater.project-epoch.net/api/manifest" | ||||
| 	configDirName = "epoch-linux" | ||||
| 	configName    = "config.toml" | ||||
| 	manifestUrl      = "https://updater.project-epoch.net/api/manifest" | ||||
| 	defaultWowPath   = "/path/to/wow" | ||||
| 	defaultLaunchCmd = "not configured" | ||||
| ) | ||||
|  | ||||
| type Config struct { | ||||
| 	WowDir string | ||||
| } | ||||
| 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() | ||||
|  | ||||
| var ( | ||||
| 	config Config | ||||
| ) | ||||
|  | ||||
| func setupConfig() { | ||||
| 	home := os.Getenv("HOME") | ||||
| 	if home == "" { | ||||
| 		log.Fatal("$HOME environment variable not set") | ||||
| 	} | ||||
|  | ||||
| 	cfgPath := filepath.Join(home, ".config", configDirName, configName) | ||||
|  | ||||
| 	if _, statErr := os.Stat(cfgPath); os.IsNotExist(statErr) { | ||||
| 		os.MkdirAll(filepath.Join(home, ".config", configDirName), 0755) | ||||
|  | ||||
| 		newConfig := &Config{ | ||||
| 			WowDir: "/path/to/wow", | ||||
| 		} | ||||
|  | ||||
| 		file, err := os.Create(cfgPath) | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		defer file.Close() | ||||
|  | ||||
| 		encoder := toml.NewEncoder(file) | ||||
| 		if err = encoder.Encode(newConfig); err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
|  | ||||
| 		fmt.Printf("Created new config at %s, edit it before running the launcher again\n", cfgPath) | ||||
| 	if helpFlag { | ||||
| 		flag.CommandLine.SetOutput(os.Stdout) | ||||
| 		fmt.Println("Epochcli Help:") | ||||
| 		flag.PrintDefaults() | ||||
| 		os.Exit(0) | ||||
| 	} | ||||
|  | ||||
| 	_, err := toml.DecodeFile(cfgPath, &config) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| 	setupConfig() | ||||
|  | ||||
| 	count, err := downloadUpdate() | ||||
| 	config, err := setupConfig(rerunConfig) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	fmt.Printf("Updated %d files\n", count) | ||||
| 	if config.WowDir == defaultWowPath { | ||||
| 		log.Fatalf("WowDir in %s is still the default setting, exiting", cfgPath) | ||||
| 	} | ||||
|  | ||||
| 	stats, err := downloadUpdate(config, forceFlag) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
|  | ||||
| 	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 { | ||||
| 		os.Exit(0) | ||||
| 	} | ||||
|  | ||||
| 	if config.EnableLauncher { | ||||
| 		if config.LaunchCmd == defaultLaunchCmd { | ||||
| 			log.Fatalf("LaunchCmd in %s is still the default setting, exiting\n", cfgPath) | ||||
| 		} | ||||
|  | ||||
| 		fmt.Println("Starting Epoch...") | ||||
| 		if runtime.GOOS == "darwin" { | ||||
| 			exec.Command("open", config.LaunchCmd).Run() | ||||
| 		} else { | ||||
| 			exec.Command(config.LaunchCmd).Run() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func downloadUpdate() (int, error) { | ||||
| 	var c 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 { | ||||
| @@ -92,42 +101,46 @@ func downloadUpdate() (int, error) { | ||||
| 			os.MkdirAll(localDir, 0755) | ||||
| 		} | ||||
|  | ||||
| 		if _, err = os.Stat(localPath); err == nil { | ||||
| 			data, err := os.ReadFile(localPath) | ||||
| 			if err != nil { | ||||
| 				return c, err | ||||
| 			} | ||||
| 			hashBytes := md5.Sum(data) | ||||
| 			hash := hex.EncodeToString(hashBytes[:]) | ||||
| 			if hash == file.Hash { | ||||
| 				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 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		fmt.Printf("Updating %s...\n", file.Path) | ||||
| 		fmt.Printf(" %s...\n", localPath) | ||||
|  | ||||
| 		outFile, err := os.Create(localPath) | ||||
| 		if err != nil { | ||||
| 			return c, err | ||||
| 			return stats, err | ||||
| 		} | ||||
| 		defer outFile.Close() | ||||
|  | ||||
| 		resp, err := http.Get(file.URL) | ||||
| 		if err != nil { | ||||
| 			return c, err | ||||
| 			return stats, err | ||||
| 		} | ||||
| 		defer resp.Body.Close() | ||||
| 		if resp.StatusCode != http.StatusOK { | ||||
| 			return c, 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 c, err | ||||
| 			return stats, err | ||||
| 		} | ||||
|  | ||||
| 		c += 1 | ||||
| 		stats.updated += 1 | ||||
| 	} | ||||
|  | ||||
| 	return c, nil | ||||
| 	return stats, nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										22
									
								
								release.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								release.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| set -e | ||||
|  | ||||
| rm -f ./*.tar.gz | ||||
| rm -f ./*.zip | ||||
|  | ||||
| GOOS=linux GOARCH=amd64 go build -o epochcli | ||||
| tar czvf epochcli-linux-amd64.tar.gz epochcli | ||||
| rm ./epochcli | ||||
|  | ||||
| GOOS=linux GOARCH=arm64 go build -o epochcli | ||||
| tar czvf epochcli-linux-arm64.tar.gz epochcli | ||||
| rm ./epochcli | ||||
|  | ||||
| GOOS=windows GOARCH=amd64 go build -o epochcli.exe | ||||
| zip -j epochcli-windows-amd64.zip epochcli.exe | ||||
| rm ./epochcli.exe | ||||
|  | ||||
| GOOS=windows GOARCH=arm64 go build -o epochcli.exe | ||||
| zip -j epochcli-windows-arm64.zip epochcli.exe | ||||
| rm ./epochcli.exe | ||||
		Reference in New Issue
	
	Block a user