Remove upgrade (#102)

* Remove upgrade

* Ask for upgrade

* Adopt installation script to unpack

* Remove unused
This commit is contained in:
Sung Won Cho 2018-09-02 16:54:29 +10:00 committed by GitHub
commit 73c5c9ac67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 165 additions and 291 deletions

View file

@ -1,6 +1,9 @@
archive:
format: binary
name_template: "dnote-{{ .Os }}-{{ .Arch }}"
format: tar.gz
format_overrides:
- goos: windows
format: zip
name_template: "dnote_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
checksum:
name_template: 'dnote-{{ .Version }}-checksums.txt'
@ -9,8 +12,7 @@ builds:
-
binary: dnote
ldflags:
- -X core.Version={{.Version}}
- -X main.apiEndpoint=https://api.dnote.io
- -X main.apiEndpoint={{ .Env.API_ENDPOINT }} -X main.versionTag={{ .Version }}
goos:
- darwin
- linux

View file

@ -3,11 +3,11 @@ release:
@echo "** Tagging and pushing..."
@git tag -a $(VERSION) -m "$(VERSION)"
@git push --tags
@goreleaser --rm-dist
@API_ENDPOINT=https://api.dnote.io goreleaser --rm-dist
.PHONY: release
build-snapshot:
@goreleaser --snapshot --rm-dist
@API_ENDPOINT=http://127.0.0.1:5000 goreleaser --snapshot --rm-dist
.PHONY: build-snapshot
clean:

View file

@ -71,6 +71,11 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
fmt.Printf("\n------------------------content------------------------\n")
fmt.Printf("%s", content)
fmt.Printf("\n-------------------------------------------------------\n")
if err := core.CheckUpdate(ctx); err != nil {
log.Error(errors.Wrap(err, "automatically checking updates").Error())
}
return nil
}
}

View file

@ -4,7 +4,6 @@ import (
"github.com/dnote/cli/core"
"github.com/dnote/cli/infra"
"github.com/dnote/cli/migrate"
"github.com/dnote/cli/upgrade"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -68,10 +67,5 @@ func Prepare(ctx infra.DnoteCtx) error {
return errors.Wrap(err, "Failed to perform migration")
}
err = upgrade.AutoUpgrade(ctx)
if err != nil {
return errors.Wrap(err, "Failed to auto upgrade")
}
return nil
}

View file

@ -117,6 +117,10 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
return errors.Wrap(err, "Failed to clear the action log")
}
if err := core.CheckUpdate(ctx); err != nil {
log.Error(errors.Wrap(err, "automatically checking updates").Error())
}
return nil
}
}
@ -170,7 +174,7 @@ func postActions(ctx infra.DnoteCtx, APIKey string, payload io.Reader) (*http.Re
}
req.Header.Set("Authorization", APIKey)
req.Header.Set("CLI-Version", core.Version)
req.Header.Set("CLI-Version", ctx.Version)
client := http.Client{}
resp, err := client.Do(req)

View file

@ -1,36 +0,0 @@
package upgrade
import (
"github.com/dnote/cli/core"
"github.com/dnote/cli/infra"
"github.com/dnote/cli/upgrade"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var example = `
dnote upgrade`
var deprecationWarning = `see https://github.com/dnote/cli/issues/96.`
func NewCmd(ctx infra.DnoteCtx) *cobra.Command {
cmd := &cobra.Command{
Use: "upgrade",
Short: "Upgrades dnote",
Example: example,
RunE: newRun(ctx),
Deprecated: deprecationWarning,
}
return cmd
}
func newRun(ctx infra.DnoteCtx) core.RunEFunc {
return func(cmd *cobra.Command, args []string) error {
if err := upgrade.Upgrade(ctx); err != nil {
return errors.Wrap(err, "Failed to upgrade dnote")
}
return nil
}
}

View file

@ -3,7 +3,6 @@ package version
import (
"fmt"
"github.com/dnote/cli/core"
"github.com/dnote/cli/infra"
"github.com/spf13/cobra"
)
@ -14,7 +13,7 @@ func NewCmd(ctx infra.DnoteCtx) *cobra.Command {
Short: "Print the version number of Dnote",
Long: "Print the version number of Dnote",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("dnote %s\n", core.Version)
fmt.Printf("dnote %s\n", ctx.Version)
},
}

View file

@ -17,10 +17,7 @@ import (
"gopkg.in/yaml.v2"
)
const (
// Version is the current version of dnote
Version = "master"
var (
// TimestampFilename is the name of the file containing upgrade info
TimestampFilename = "timestamps"
// DnoteDirName is the name of the directory containing dnote files

100
core/upgrade.go Normal file
View file

@ -0,0 +1,100 @@
package core
import (
"context"
"fmt"
"time"
"github.com/dnote/cli/infra"
"github.com/dnote/cli/log"
"github.com/dnote/cli/utils"
"github.com/google/go-github/github"
"github.com/pkg/errors"
)
// upgradeInterval is 3 weeks
var upgradeInterval int64 = 86400 * 7 * 3
// shouldCheckUpdate checks if update should be checked
func shouldCheckUpdate(ctx infra.DnoteCtx) (bool, error) {
timestamp, err := ReadTimestamp(ctx)
if err != nil {
return false, errors.Wrap(err, "Failed to get timestamp content")
}
now := time.Now().Unix()
return now-timestamp.LastUpgrade > upgradeInterval, nil
}
func touchLastUpgrade(ctx infra.DnoteCtx) error {
timestamp, err := ReadTimestamp(ctx)
if err != nil {
return errors.Wrap(err, "Failed to get timestamp content")
}
now := time.Now().Unix()
timestamp.LastUpgrade = now
if err := WriteTimestamp(ctx, timestamp); err != nil {
return errors.Wrap(err, "Failed to write the updated timestamp to the file")
}
return nil
}
func checkVersion(ctx infra.DnoteCtx) error {
log.Infof("current version is %s\n", ctx.Version)
// Fetch the latest version
gh := github.NewClient(nil)
releases, _, err := gh.Repositories.ListReleases(context.Background(), "dnote", "cli", nil)
if err != nil {
return errors.Wrap(err, "fetching releases")
}
latest := releases[0]
latestVersion := (*latest.TagName)[1:]
log.Infof("latest version is %s\n", latestVersion)
if latestVersion == ctx.Version {
log.Success("you are up-to-date\n\n")
} else {
log.Infof("to upgrade, see https://github.com/dnote/cli/blob/master/README.md\n")
}
return nil
}
// CheckUpdate triggers update if needed
func CheckUpdate(ctx infra.DnoteCtx) error {
shouldCheck, err := shouldCheckUpdate(ctx)
if err != nil {
return errors.Wrap(err, "checking if dnote should check update")
}
if !shouldCheck {
return nil
}
err = touchLastUpgrade(ctx)
if err != nil {
return errors.Wrap(err, "updating the last upgrade timestamp")
}
fmt.Printf("\n")
willCheck, err := utils.AskConfirmation("check for upgrade?", true)
if err != nil {
return errors.Wrap(err, "getting user confirmation")
}
if !willCheck {
return nil
}
err = checkVersion(ctx)
if err != nil {
return errors.Wrap(err, "checking version")
}
return nil
}

View file

@ -6,6 +6,7 @@ type DnoteCtx struct {
HomeDir string
DnoteDir string
APIEndpoint string
Version string
}
// Config holds dnote configuration

View file

@ -12,7 +12,7 @@ not_supported() {
exit 1
}
install() {
get_platform() {
UNAME=$(uname)
if [ "$UNAME" != "Linux" -a "$UNAME" != "Darwin" -a "$UNAME" != "OpenBSD" ] ; then
@ -22,46 +22,68 @@ install() {
if [ "$UNAME" = "Darwin" ]; then
OSX_ARCH=$(uname -m)
if [ "${OSX_ARCH}" = "x86_64" ]; then
PLATFORM="darwin-amd64"
platform="darwin_amd64"
else
not_supported
fi
elif [ "$UNAME" = "Linux" ]; then
LINUX_ARCH=$(uname -m)
if [ "${LINUX_ARCH}" = "x86_64" ]; then
PLATFORM="linux-amd64"
platform="linux_amd64"
elif [ "${LINUX_ARCH}" = "i686" ]; then
PLATFORM="linux-386"
platform="linux_386"
else
not_supported
fi
elif [ "$UNAME" = "OpenBSD" ]; then
OPENBSD_ARCH=$(uname -m)
if [ "${OPENBSD_ARCH}" = "x86_64" ]; then
PLATFORM="openbsd-amd64"
platform="openbsd_amd64"
elif [ "${OPENBSD_ARCH}" = "i686" ]; then
PLATFORM="openbsd-386"
platform="openbsd_386"
else
not_supported
fi
fi
LATEST=$(curl -s https://api.github.com/repos/dnote/cli/tags | grep -Eo '"name":[ ]*"v[0-9]*\.[0-9]*\.[0-9]*",' | head -n 1 | sed 's/[," ]//g' | cut -d ':' -f 2)
URL="https://github.com/dnote/cli/releases/download/$LATEST/dnote-$PLATFORM"
DEST=${DEST:-/usr/local/bin/dnote}
echo $platform
}
get_version() {
LATEST=$(curl -s https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/tags | grep -Eo '"name":[ ]*"v[0-9]*\.[0-9]*\.[0-9]*",' | head -n 1 | sed 's/[," ]//g' | cut -d ':' -f 2)
if [ -z $LATEST ]; then
echo "Error fetching latest version. Please try again."
exit 1
fi
echo "Downloading Dnote binary from $URL to $DEST"
if curl -L --progress-bar $URL -o $DEST; then
chmod +x $DEST
# remove the preceding 'v'
echo ${LATEST#v}
}
execute() {
echo "downloading Dnote v${LATEST}..."
echo ${URL}
if curl -L --progress-bar $URL -o "${TMPDIR}/${TARBALL}"; then
(cd "${TMPDIR}" && tar -xzf "${TARBALL}")
install -d "${BINDIR}"
install "${TMPDIR}/${BINARY}" "${BINDIR}/"
echo "Successfully installed Dnote"
else
echo "Installation failed. You might need elevated permission."
exit 1
fi
}
install
REPO_OWNER=dnote
REPO_NAME=cli
PLATFORM=$(get_platform)
LATEST=$(get_version)
TARBALL="dnote_${LATEST}_${PLATFORM}.tar.gz"
URL="https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/v${LATEST}/${TARBALL}"
TMPDIR="$(mktemp -d)"
BINDIR=${BINDIR:-/usr/local/bin}
BINARY=dnote
execute

View file

@ -19,13 +19,13 @@ import (
"github.com/dnote/cli/cmd/ls"
"github.com/dnote/cli/cmd/remove"
"github.com/dnote/cli/cmd/sync"
"github.com/dnote/cli/cmd/upgrade"
"github.com/dnote/cli/cmd/version"
"github.com/dnote/cli/cmd/view"
)
// apiEndpoint is populated during link time
// apiEndpoint and versionTag are populated during link time
var apiEndpoint string
var versionTag = "master"
func main() {
ctx, err := newCtx()
@ -45,7 +45,6 @@ func main() {
root.Register(ls.NewCmd(ctx))
root.Register(sync.NewCmd(ctx))
root.Register(version.NewCmd(ctx))
root.Register(upgrade.NewCmd(ctx))
root.Register(cat.NewCmd(ctx))
root.Register(view.NewCmd(ctx))
@ -66,6 +65,7 @@ func newCtx() (infra.DnoteCtx, error) {
HomeDir: homeDir,
DnoteDir: dnoteDir,
APIEndpoint: apiEndpoint,
Version: versionTag,
}
return ret, nil

View file

@ -222,7 +222,7 @@ func migrateToV5(ctx infra.DnoteCtx) error {
case migrateToV5ActionEditNote:
var oldData migrateToV5PreEditNoteData
if err = json.Unmarshal(action.Data, &oldData); err != nil {
return errors.Wrapf(err, "unmarshalling old data of an edit note action %s", action.ID)
return errors.Wrapf(err, "unmarshalling old data of an edit note action %d", action.ID)
}
migratedData := migrateToV5PostEditNoteData{

View file

@ -1,3 +1,7 @@
#!/bin/bash
rm $(which dnote) $GOPATH/bin/cli && go install -ldflags "-X main.apiEndpoint=http://127.0.0.1:5000" . && ln -s $GOPATH/bin/cli /usr/local/bin/dnote
# dev.sh builds a new binary and replaces the old one in the PATH with it
rm "$(which dnote)" $GOPATH/bin/cli
make build-snapshot
ln -s $GOPATH/src/github.com/dnote/cli/dist/darwin_amd64/dnote /usr/local/bin/dnote

View file

@ -1,181 +0,0 @@
package upgrade
import (
"context"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path"
"runtime"
"time"
"github.com/dnote/cli/core"
"github.com/dnote/cli/infra"
"github.com/dnote/cli/log"
"github.com/dnote/cli/utils"
"github.com/google/go-github/github"
"github.com/pkg/errors"
)
// upgradeInterval is 3 weeks
var upgradeInterval int64 = 86400 * 7 * 3
// getAsset finds the asset to download from the liast of assets in a release
func getAsset(release *github.RepositoryRelease) *github.ReleaseAsset {
filename := fmt.Sprintf("dnote-%s-%s", runtime.GOOS, runtime.GOARCH)
for _, asset := range release.Assets {
if *asset.Name == filename {
return &asset
}
}
return nil
}
// shouldCheckUpdate checks if update should be checked
func shouldCheckUpdate(ctx infra.DnoteCtx) (bool, error) {
timestamp, err := core.ReadTimestamp(ctx)
if err != nil {
return false, errors.Wrap(err, "Failed to get timestamp content")
}
now := time.Now().Unix()
return now-timestamp.LastUpgrade > upgradeInterval, nil
}
func touchLastUpgrade(ctx infra.DnoteCtx) error {
timestamp, err := core.ReadTimestamp(ctx)
if err != nil {
return errors.Wrap(err, "Failed to get timestamp content")
}
now := time.Now().Unix()
timestamp.LastUpgrade = now
if err := core.WriteTimestamp(ctx, timestamp); err != nil {
return errors.Wrap(err, "Failed to write the updated timestamp to the file")
}
return nil
}
// AutoUpgrade triggers update if needed
func AutoUpgrade(ctx infra.DnoteCtx) error {
shouldCheck, err := shouldCheckUpdate(ctx)
if err != nil {
return errors.Wrap(err, "Failed to check if dnote should check update")
}
if shouldCheck {
willCheck, err := utils.AskConfirmation("check for upgrade?", true)
if err != nil {
return errors.Wrap(err, "Failed to get user confirmation for checking upgrade")
}
err = touchLastUpgrade(ctx)
if err != nil {
return errors.Wrap(err, "Failed to update last upgrade timestamp")
}
if willCheck {
if err := Upgrade(ctx); err != nil {
return errors.Wrap(err, "Failed to upgrade")
}
}
}
return nil
}
func Upgrade(ctx infra.DnoteCtx) error {
log.Infof("current version is %s\n", core.Version)
// Fetch the latest version
gh := github.NewClient(nil)
releases, _, err := gh.Repositories.ListReleases(context.Background(), "dnote", "cli", nil)
if err != nil {
return err
}
latest := releases[0]
latestVersion := (*latest.TagName)[1:]
if err != nil {
return err
}
log.Infof("latest version is %s\n", latestVersion)
// Check if up to date
if latestVersion == core.Version {
log.Success("you are up-to-date\n\n")
err = touchLastUpgrade(ctx)
if err != nil {
return errors.Wrap(err, "Failed to update the upgrade timestamp")
}
return nil
}
asset := getAsset(latest)
if asset == nil {
err = touchLastUpgrade(ctx)
if err != nil {
return errors.Wrap(err, "Failed to update the upgrade timestamp")
}
return errors.Errorf("Could not find the release for %s %s", runtime.GOOS, runtime.GOARCH)
}
// Download temporary file
log.Infof("downloading: %s\n", latestVersion)
tmpPath := path.Join(os.TempDir(), "dnote_update")
out, err := os.Create(tmpPath)
if err != nil {
return err
}
defer out.Close()
resp, err := http.Get(*asset.BrowserDownloadURL)
if err != nil {
return err
}
defer resp.Body.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
// Override the binary
cmdPath, err := exec.LookPath("dnote")
if err != nil {
return err
}
err = os.Rename(tmpPath, cmdPath)
if err != nil {
return err
}
// Make it executable
err = os.Chmod(cmdPath, 0755)
if err != nil {
return err
}
err = touchLastUpgrade(ctx)
if err != nil {
return errors.Wrap(err, "Upgrade is done, but failed to update the last_upgrade timestamp.")
}
log.Successf("updated: v%s -> v%s\n", core.Version, latestVersion)
log.Plain("changelog: https://github.com/dnote/cli/releases\n\n")
return nil
}

View file

@ -1,37 +0,0 @@
@echo off
set DNOTEPATH=%PROGRAMFILES%\Dnote CLI
set DNOTEDL=dnote-windows-amd64.exe
set DNOTETARGET=%DNOTEPATH%\dnote.exe
echo Checking for directory...
if not exist "%DNOTEPATH%\" (
echo Creating directory...
mkdir "%DNOTEPATH%"
)
echo Moving program to target directory...
move /Y %DNOTEDL% "%DNOTETARGET%"
echo "Adding directory to user PATH..."
REM retrieve only the user's PATH from registry,
REM to avoid attempting (and probably failing) to overwrite the
REM system path
set Key=HKCU\Environment
FOR /F "tokens=2* skip=1" %%G IN ('REG QUERY %Key% /v PATH') DO (
echo %%H > user_path_backup.txt
set t=%%H
set "NEWPATH="
:loop
for /f "delims=; tokens=1*" %%a in ("%t%") do (
set t=%%b
if not "%%a" == "%DNOTEPATH%" (
if defined NEWPATH (
set NEWPATH=%NEWPATH%;%%a
) else (
set NEWPATH=%%a
)
)
)
if defined t goto :loop
)
set NEWPATH=%NEWPATH%;%DNOTEPATH%
setx PATH "%NEWPATH%"