Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add update command which looks at os and tries to update #42

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/build_test_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,17 @@ jobs:
run: |
cp ./src/author.txt ./dist

tag=$(git describe --tags --abbrev=0)
#linux build
release_name_linux="cocommit_go-$tag-linux"
release_name_linux="cocommit-linux"

tar -C ./dist -czvf "${release_name_linux}.tar.gz" cocommit_go-linux ./author.txt

#windows build
release_name_win="cocommit_go-$tag-win"
release_name_win="cocommit-win"
tar -C ./dist -czvf "${release_name_win}.tar.gz" cocommit_go-windows ./author.txt

#mac build
release_name_mac="cocommit_go-$tag-mac"
release_name_mac="cocommit-darwin-x86_64"
tar -C ./dist -czvf "${release_name_mac}.tar.gz" cocommit_go-darwin ./author.txt
- name: Release project
uses: softprops/action-gh-release@v1
Expand Down
13 changes: 12 additions & 1 deletion ci/build_test_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func main() {

for _, goos := range geese {
path := fmt.Sprintf("/dist/")
filename := fmt.Sprintf("/dist/cocommit_go-%s", goos)
filename := fmt.Sprintf("/dist/cocommit-%s", goos)
// build application
// write the build output to the host
build := test.
Expand All @@ -56,6 +56,17 @@ func main() {

}

// extra step to build for aarch on darwin
path := fmt.Sprintf("/dist/")
filename := fmt.Sprintf("/dist/cocommit-darwin-aarch64")

build := test.
WithEnvVariable("GOOS", "darwin").
WithEnvVariable("GOARCH", "arm64").
WithExec([]string{"go", "build", "-o", filename}).WithEnvVariable("CI", "true")

buildDir = buildDir.WithDirectory(path, build.Directory(path))

_, err = buildDir.Export(ctx, ".")
if err != nil {
panic(err)
Expand Down
213 changes: 213 additions & 0 deletions src/cmd/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package cmd

import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"

"github.com/spf13/cobra"
)

// updateCmd represents the update command
var updateCmd = &cobra.Command{
Use: "update",
Short: "Tries to update the cocommit cli tool by either running the update script or by running the go get command if the -g flag is set",
Long: `This command will try to update the cocommit cli tool by either running the update script or by running the go get Command if the -g flag is set.`,
Run: func(cmd *cobra.Command, args []string) {
gflag, _ := cmd.Flags().GetBool("go-get")

if gflag {
fmt.Println("Running go get command to update cocommit cli tool")
cmd := exec.Command("go", "get", "-u", "github.com/Slug-Boi/cocommit")
err := cmd.Run()
if err != nil {
fmt.Println("Error running go get command")
}
fmt.Println("Cocommit cli tool updated successfully")
} else {
fmt.Println("Running update script to update cocommit cli tool")
updateScript()
}

},
}

func cleanup() {
os.Remove("cocommit.tar.gz")
}

func updateScript() {

exec_path, err := os.Executable()
if err != nil {
fmt.Println("Error getting executable path")
}
if filepath.Base(exec_path) == "main" {
fmt.Println("Cancelling update running as source code")
return
}

exec_path, err = filepath.EvalSymlinks(exec_path)
if err != nil {
log.Fatal(err)
}

file, err := os.Create("cocommit.tar.gz")
if err != nil {
fmt.Println("Error creating file")
}

defer cleanup()

defer file.Close()

var resp *http.Response
switch runtime.GOOS {
case "darwin":
fmt.Println("Downloading mac version")
if runtime.GOARCH == "amd64" {
resp, err = http.Get("https://github.com/Slug-Boi/cocommit/releases/latest/download/cocommit-darwin-x86_64.tar.gz")
} else {
resp, err = http.Get("https://github.com/Slug-Boi/cocommit/releases/latest/download/cocommit-darwin-aarch64.tar.gz")
}
case "windows":
fmt.Println("Downloading windows version")
resp, err = http.Get("https://github.com/Slug-Boi/cocommit/releases/latest/download/cocommit-win.tar.gz")
default:
fmt.Println("Downloading linux version")
resp, err = http.Get("https://github.com/Slug-Boi/cocommit/releases/latest/download/cocommit-linux.tar.gz")
}

if err != nil {
fmt.Println("Error downloading file")
}

defer resp.Body.Close()
_, err = io.Copy(file, resp.Body)
if err != nil {
fmt.Println("Error copying file")
}

r, err := os.Open("cocommit.tar.gz")
if err != nil {
fmt.Println("Error opening file")
}
err = unzipper("./", r)
if err != nil {
fmt.Println("Error unzipping file")
}

swapper(exec_path)

fmt.Println("Cocommit cli tool updated successfully")
}

func swapper(exec_path string) {

regExp, err := regexp.Compile("cocommit_go-darwin")
if err != nil {
log.Fatal(err)
}

var new_binary string

err = filepath.Walk("./", func(path string, info os.FileInfo, err error) error {
if err == nil && regExp.MatchString(info.Name()) {
new_binary = info.Name()
return nil
}
return nil
})
if err != nil {
log.Fatal(err)
}

defer os.Remove(new_binary)

if new_binary != "" {
err = os.Rename(new_binary, exec_path)
if err != nil {
log.Fatal(err)
}
}

}

func unzipper(dst string, r io.Reader) error {
gzr, err := gzip.NewReader(r)
if err != nil {
return err
}
defer gzr.Close()

tr := tar.NewReader(gzr)

for {
header, err := tr.Next()
Fixed Show fixed Hide fixed

switch {

// if no more files are found return
case err == io.EOF:
return nil

// return any other error
case err != nil:
return err

// if the header is nil, just skip it (not sure how this happens)
case header == nil:
continue
}

// the target location where the dir/file should be created
target := filepath.Join(dst, header.Name)

// ensure the target path is within the destination directory
if !strings.HasPrefix(target, filepath.Clean(dst)+string(os.PathSeparator)) {
return fmt.Errorf("illegal file path: %s", target)
}

// check the file type
switch header.Typeflag {

// if its a dir and it doesn't exist create it
case tar.TypeDir:
if _, err := os.Stat(target); err != nil {
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
}

// if it's a file create it
case tar.TypeReg:
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
if err != nil {
return err
}

// copy over contents
if _, err := io.Copy(f, tr); err != nil {
return err
}

// manually close here after each file operation; defering would cause each file close
// to wait until all operations have completed.
f.Close()
}
}
}

func init() {
rootCmd.AddCommand(updateCmd)
updateCmd.Flags().BoolP("go-get", "g", false, "Use the go get command to update the cocommit cli tool")
}