func Stdin(val io.Reader) OptionSet {
	return func(o *Options) {
		o.Stdin = val
	}
}
Stdin specifies the process's standard input.
If Stdin is nil, the process reads from the null device (os.DevNull).
If Stdin is an *os.File, the process's standard input is connected
directly to that file.
Otherwise, during the execution of the command a separate
goroutine reads from Stdin and delivers that data to the command
over a pipe. In this case, Wait does not complete until the goroutine
stops copying, either because it has reached the end of Stdin
(EOF or a read error) or because writing to the pipe returned an error.
package fs
import (
	"bufio"
	"fmt"
	"github.com/google/go-github/github"
	"github.com/hashicorp/go-version"
	"github.com/kataras/go-errors"
	"io"
	"os"
	"os/exec"
	"context"
)
var (
	errUpdaterUnknown = errors.New("Updater: Unknown error: %s")
	errCantFetchRepo  = errors.New("Updater: Error while trying to fetch the repository: %s. Trace: %s")
	errAccessRepo     = errors.New("Updater: Couldn't access to the github repository, please make sure you're connected to the internet")
)
type Updater struct {
	currentVersion *version.Version
	latestVersion  *version.Version
	owner          string
	repo           string
}
func GetUpdater(owner string, repo string, currentReleaseVersion string) (*Updater, error) {
	client := github.NewClient(nil)  
	ctx := context.TODO()
	latestRelease, response, err := client.Repositories.GetLatestRelease(ctx, owner, repo)
	if err != nil {
		return nil, errCantFetchRepo.Format(owner+":"+repo, err)
	}
	if c := response.StatusCode; c != 200 && c != 201 && c != 202 && c != 301 && c != 302 && c == 304 {
		return nil, errAccessRepo
	}
	currentVersion, err := version.NewVersion(currentReleaseVersion)
	if err != nil {
		return nil, err
	}
	latestVersion, err := version.NewVersion(*latestRelease.TagName)
	if err != nil {
		return nil, err
	}
	u := &Updater{
		currentVersion: currentVersion,
		latestVersion:  latestVersion,
		owner:          owner,
		repo:           repo,
	}
	return u, nil
}
func (u *Updater) HasUpdate() (bool, string) {
	return u.currentVersion.LessThan(u.latestVersion), u.latestVersion.String()
}
var (
	DefaultUpdaterAlreadyInstalledMessage = "\nThe latest version '%s' was already installed."
)
func (u *Updater) Run(setters ...optionSetter) bool {
	opt := &Options{Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr, Silent: false}  
	for _, setter := range setters {
		setter.Set(opt)
	}
	writef := func(s string, a ...interface{}) {
		if !opt.Silent {
			opt.Stdout.Write([]byte(fmt.Sprintf(s, a...)))
		}
	}
	has, v := u.HasUpdate()
	if has {
		var scanner *bufio.Scanner
		if opt.Stdin != nil {
			scanner = bufio.NewScanner(opt.Stdin)
		}
		shouldProceedUpdate := func() bool {
			return shouldProceedUpdate(scanner)
		}
		writef("\nA newer version has been found[%s > %s].\n"+
			"Release notes: %s\n"+
			"Update now?[%s]: ",
			u.latestVersion.String(), u.currentVersion.String(),
			fmt.Sprintf("https://github.com/%s/%s/releases/latest", u.owner, u.repo),
			DefaultUpdaterYesInput[0]+"/n")
		if shouldProceedUpdate() {
			if !opt.Silent {
				finish := ShowIndicator(opt.Stdout, true)
				defer func() {
					finish <- true
				}()
			}
			cmd := exec.Command("go", "get", "-u", fmt.Sprintf("github.com/%s/%s", u.owner, u.repo))
			cmd.Stdout = opt.Stdout
			cmd.Stderr = opt.Stderr
			if err := cmd.Run(); err != nil {
				writef("\nError while trying to get the package: %s.", err.Error())
			}
			writef("\010\010\010")  
			writef("Update has been installed, current version: %s. Please re-start your App.\n", u.latestVersion.String())
			return true
		}
	} else {
		writef(fmt.Sprintf(DefaultUpdaterAlreadyInstalledMessage, v))
	}
	return false
}
var DefaultUpdaterYesInput = [...]string{"y", "yes", "nai", "si"}
func shouldProceedUpdate(sc *bufio.Scanner) bool {
	silent := sc == nil
	inputText := ""
	if !silent {
		if sc.Scan() {
			inputText = sc.Text()
		}
	}
	for _, s := range DefaultUpdaterYesInput {
		if inputText == s {
			return true
		}
	}
	return silent
}
type Options struct {
	Silent bool
	Stdin io.Reader
	Stdout io.Writer
	Stderr io.Writer
}
func (o *Options) Set(main *Options) {
	main.Silent = o.Silent
}
type optionSetter interface {
	Set(*Options)
}
type OptionSet func(*Options)
func (o OptionSet) Set(main *Options) {
	o(main)
}
func Silent(val bool) OptionSet {
	return func(o *Options) {
		o.Silent = val
	}
}