github.com/emmahsax/go-git-helper@v0.0.8-0.20240519163017-907b9de0fa52/cmd/update/update.go (about)

     1  package update
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net/http"
     7  	"os"
     8  	"os/user"
     9  	"runtime"
    10  	"strings"
    11  
    12  	"github.com/emmahsax/go-git-helper/internal/executor"
    13  	"github.com/emmahsax/go-git-helper/internal/utils"
    14  	"github.com/spf13/cobra"
    15  	"github.com/tidwall/gjson"
    16  )
    17  
    18  type Update struct {
    19  	Debug      bool
    20  	Executor   executor.ExecutorInterface
    21  	Owner      string
    22  	Repository string
    23  }
    24  
    25  var (
    26  	asset   = "git-helper_" + runtime.GOOS + "_" + runtime.GOARCH
    27  	newPath = "/usr/local/bin/git-helper" // This is for linux and mac based systems only
    28  )
    29  
    30  func NewCommand(packageOwner, packageRepository string) *cobra.Command {
    31  	var (
    32  		debug bool
    33  	)
    34  
    35  	cmd := &cobra.Command{
    36  		Use:                   "update",
    37  		Short:                 "Updates Git Helper with the newest version on GitHub",
    38  		Args:                  cobra.ExactArgs(0),
    39  		DisableFlagsInUseLine: true,
    40  		RunE: func(cmd *cobra.Command, args []string) error {
    41  			newUpdate(packageOwner, packageRepository, debug, executor.NewExecutor(debug)).execute()
    42  			return nil
    43  		},
    44  	}
    45  
    46  	cmd.Flags().BoolVar(&debug, "debug", false, "enables debug mode")
    47  
    48  	return cmd
    49  }
    50  
    51  func newUpdate(owner, repository string, debug bool, executor executor.ExecutorInterface) *Update {
    52  	return &Update{
    53  		Debug:      debug,
    54  		Executor:   executor,
    55  		Owner:      owner,
    56  		Repository: repository,
    57  	}
    58  }
    59  
    60  func (u *Update) execute() {
    61  	u.downloadGitHelper()
    62  	u.moveGitHelper()
    63  	u.setPermissions()
    64  	u.outputNewVersion()
    65  }
    66  
    67  func (u *Update) downloadGitHelper() {
    68  	fmt.Println("Installing latest git-helper version")
    69  
    70  	releaseURL := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", u.Owner, u.Repository)
    71  	downloadURL := u.getDownloadURL(u.fetchReleaseBody(releaseURL))
    72  	binaryName := strings.Split(downloadURL, "/")[len(strings.Split(downloadURL, "/"))-1]
    73  	u.downloadAndSaveBinary(downloadURL, binaryName)
    74  }
    75  
    76  func (u *Update) fetchReleaseBody(releaseURL string) []byte {
    77  	resp, err := http.Get(releaseURL)
    78  	if err != nil {
    79  		utils.HandleError(err, u.Debug, nil)
    80  		return []byte{}
    81  	}
    82  	defer resp.Body.Close()
    83  
    84  	body, err := io.ReadAll(resp.Body)
    85  	if err != nil {
    86  		utils.HandleError(err, u.Debug, nil)
    87  		return []byte{}
    88  	}
    89  
    90  	return body
    91  }
    92  
    93  func (u *Update) getDownloadURL(body []byte) string {
    94  	var downloadURL string
    95  	switch runtime.GOOS {
    96  	case "darwin":
    97  		downloadURL = gjson.Get(string(body), "assets.#(name==\""+asset+"\").browser_download_url").String()
    98  	case "linux":
    99  		downloadURL = gjson.Get(string(body), "assets.#(name==\""+asset+"\").browser_download_url").String()
   100  	default:
   101  		fmt.Println("Unsupported operating system:", runtime.GOOS)
   102  	}
   103  
   104  	return downloadURL
   105  }
   106  
   107  func (u *Update) downloadAndSaveBinary(downloadURL, binaryName string) {
   108  	resp, err := http.Get(downloadURL)
   109  	if err != nil {
   110  		utils.HandleError(err, u.Debug, nil)
   111  		return
   112  	}
   113  	defer resp.Body.Close()
   114  
   115  	out, err := os.Create(binaryName)
   116  	if err != nil {
   117  		utils.HandleError(err, u.Debug, nil)
   118  		return
   119  	}
   120  	defer out.Close()
   121  
   122  	_, err = io.Copy(out, resp.Body)
   123  	if err != nil {
   124  		utils.HandleError(err, u.Debug, nil)
   125  		return
   126  	}
   127  }
   128  
   129  func (u *Update) moveGitHelper() {
   130  	output, err := u.Executor.Exec("actionAndOutput", "sudo", "mv", "./"+asset, newPath)
   131  	if err != nil {
   132  		utils.HandleError(err, u.Debug, nil)
   133  		return
   134  	}
   135  
   136  	fmt.Printf("%s", string(output))
   137  }
   138  
   139  func (u *Update) setPermissions() {
   140  	currentUser, err := user.Current()
   141  	if err != nil {
   142  		utils.HandleError(err, u.Debug, nil)
   143  		return
   144  	}
   145  
   146  	output, err := u.Executor.Exec("actionAndOutput", "sudo", "chown", currentUser.Username+":staff", newPath)
   147  	if err != nil {
   148  		utils.HandleError(err, u.Debug, nil)
   149  		return
   150  	}
   151  
   152  	fmt.Printf("%s", string(output))
   153  
   154  	output, err = u.Executor.Exec("actionAndOutput", "sudo", "chmod", "+x", newPath)
   155  	if err != nil {
   156  		utils.HandleError(err, u.Debug, nil)
   157  		return
   158  	}
   159  
   160  	fmt.Printf("%s", string(output))
   161  }
   162  
   163  func (u *Update) outputNewVersion() {
   164  	output, err := u.Executor.Exec("actionAndOutput", "git-helper", "version")
   165  	if err != nil {
   166  		utils.HandleError(err, u.Debug, nil)
   167  		return
   168  	}
   169  	fmt.Printf("Installed %s", string(output))
   170  }