feat: support auto update

feat: support run on windows
master v0.0.2
xuthus5 4 months ago
parent eea0c51b26
commit baea60d195
  1. 4
      cmd.go
  2. 2
      go.mod
  3. 40
      output.go
  4. 150
      update.go
  5. 7
      utils.go

@ -22,7 +22,7 @@ var (
)
func init() {
// create a new mder folder
// create a new site folder
rootCmd.AddCommand(initCmd())
// generate static website
rootCmd.AddCommand(deployCmd())
@ -30,6 +30,8 @@ func init() {
rootCmd.AddCommand(newCmd())
// run serve locally
rootCmd.AddCommand(serveCmd())
// auto update
rootCmd.AddCommand(updateCmd())
}
func main() {

@ -5,6 +5,7 @@ go 1.18
require (
github.com/abhinav/goldmark-toc v0.2.1
github.com/gin-gonic/gin v1.8.1
github.com/guonaihong/gout v0.3.1
github.com/radovskyb/watcher v1.0.7
github.com/spf13/cobra v1.5.0
github.com/yuin/goldmark v1.4.13
@ -26,6 +27,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect

@ -6,6 +6,7 @@ import (
"math"
"os"
"os/exec"
"runtime"
"sort"
"text/template"
)
@ -39,15 +40,26 @@ type PostData struct {
// check 检测目标
func (o *Outter) check() {
var args []string
switch runtime.GOOS {
case "windows":
args = []string{"cmd.exe", "/C", "rmdir", "/S", "/Q", "dist"}
default:
args = []string{"rm", "-rf", "./dist"}
}
var cmd = exec.Command(args[0], args[1:]...)
if err := cmd.Run(); err != nil {
sout(cmd.String())
serr("clear dist directory failed: %v", err)
}
if !isExist("./dist") {
if err := mkdir("./dist"); err != nil {
sfault("create dist directory failed: %v", err)
}
}
if err := exec.Command("rm", "-rf", "./dist/*").Run(); err != nil {
sfault("clear dist directory failed: %v", err)
}
}
func (o *Outter) createDir(fp string) error {
@ -61,18 +73,28 @@ func (o *Outter) createDir(fp string) error {
// sourceCopy 资源拷贝 将主题的资源拷贝到目标文件夹中
func (o *Outter) sourceCopy() {
themePath := fmt.Sprintf("./themes/%s/", o.Config.Theme)
destPath := "./dist/"
cmd := exec.Command("cp", "-r", themePath+"css", destPath)
var args []string
switch runtime.GOOS {
case "windows":
args = []string{"cmd.exe", "/C", "xcopy", "/e"}
default:
args = []string{"cp", "-r"}
}
themePath := slash(fmt.Sprintf("./themes/%s/", o.Config.Theme))
destPath := slash("./dist/")
cmd := exec.Command(args[0], append(args, themePath+"css", destPath)...)
if err := cmd.Run(); err != nil {
sout(cmd.String())
sfault("copy theme css source failed: %v", err)
}
cmd = exec.Command("cp", "-r", themePath+"js", destPath)
cmd = exec.Command(args[0], append(args, themePath+"js", destPath)...)
if err := cmd.Run(); err != nil {
sout(cmd.String())
sfault("copy theme js source failed: %v", err)
}
cmd = exec.Command("cp", "-r", themePath+"images", destPath)
cmd = exec.Command(args[0], append(args, themePath+"images", destPath)...)
if err := cmd.Run(); err != nil {
sout(cmd.String())
sfault("copy theme images source failed: %v", err)
}
}

@ -0,0 +1,150 @@
package main
import (
"fmt"
"github.com/spf13/cobra"
"os/exec"
"time"
"github.com/guonaihong/gout"
)
func updateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Short: "mder auto update",
Example: "mder update",
Run: func(cmd *cobra.Command, args []string) {
commit, err := GetRepoLatestCommit()
if err != nil {
sfault("get mder version failed: %v", err)
}
sout("-----\nmder latest version: %s\n更新中...\n", commit.Sha)
var url = fmt.Sprintf("gitter.top/mder/mder@%s", commit.Sha)
genO, err := exec.Command("go", "install", url).CombinedOutput()
if err != nil {
serr("install: go install %s\nupdate failed: %v\n", url, err)
return
}
sout("%supdate success", string(genO))
},
}
return cmd
}
type RepoCommits []*RepoCommit
type RepoCommit struct {
Author struct {
Active bool `json:"active"`
AvatarURL string `json:"avatar_url"`
Created time.Time `json:"created"`
Description string `json:"description"`
Email string `json:"email"`
FollowersCount int `json:"followers_count"`
FollowingCount int `json:"following_count"`
FullName string `json:"full_name"`
ID int `json:"id"`
IsAdmin bool `json:"is_admin"`
Language string `json:"language"`
LastLogin time.Time `json:"last_login"`
Location string `json:"location"`
Login string `json:"login"`
ProhibitLogin bool `json:"prohibit_login"`
Restricted bool `json:"restricted"`
StarredReposCount int `json:"starred_repos_count"`
Visibility string `json:"visibility"`
Website string `json:"website"`
} `json:"author"`
Commit struct {
Author struct {
Date string `json:"date"`
Email string `json:"email"`
Name string `json:"name"`
} `json:"author"`
Committer struct {
Date string `json:"date"`
Email string `json:"email"`
Name string `json:"name"`
} `json:"committer"`
Message string `json:"message"`
Tree struct {
Created time.Time `json:"created"`
Sha string `json:"sha"`
URL string `json:"url"`
} `json:"tree"`
URL string `json:"url"`
Verification struct {
Payload string `json:"payload"`
Reason string `json:"reason"`
Signature string `json:"signature"`
Signer struct {
Email string `json:"email"`
Name string `json:"name"`
Username string `json:"username"`
} `json:"signer"`
Verified bool `json:"verified"`
} `json:"verification"`
} `json:"commit"`
Committer struct {
Active bool `json:"active"`
AvatarURL string `json:"avatar_url"`
Created time.Time `json:"created"`
Description string `json:"description"`
Email string `json:"email"`
FollowersCount int `json:"followers_count"`
FollowingCount int `json:"following_count"`
FullName string `json:"full_name"`
ID int `json:"id"`
IsAdmin bool `json:"is_admin"`
Language string `json:"language"`
LastLogin time.Time `json:"last_login"`
Location string `json:"location"`
Login string `json:"login"`
ProhibitLogin bool `json:"prohibit_login"`
Restricted bool `json:"restricted"`
StarredReposCount int `json:"starred_repos_count"`
Visibility string `json:"visibility"`
Website string `json:"website"`
} `json:"committer"`
Created time.Time `json:"created"`
Files []struct {
Filename string `json:"filename"`
} `json:"files"`
HTMLURL string `json:"html_url"`
Parents []struct {
Created time.Time `json:"created"`
Sha string `json:"sha"`
URL string `json:"url"`
} `json:"parents"`
Sha string `json:"sha"`
Stats struct {
Additions int `json:"additions"`
Deletions int `json:"deletions"`
Total int `json:"total"`
} `json:"stats"`
URL string `json:"url"`
}
// GetRepoLatestCommit 获取仓库最新提交记录
func GetRepoLatestCommit() (*RepoCommit, error) {
var commits RepoCommits
api := "https://gitter.top/api/v1/repos/mder/mder/commits"
if err := gout.GET(api).SetHeader(gout.H{
"Accept": "application/json",
"User-Agent": "mder/beta",
}).SetQuery(gout.H{
"page": 1,
"limit": 5,
}).SetTimeout(time.Second * 3).BindJSON(&commits).Do(); err != nil {
return nil, err
}
if len(commits) == 0 {
return nil, fmt.Errorf("empty commit")
}
return commits[0], nil
}

@ -129,3 +129,10 @@ func sfault(format string, args ...interface{}) {
_, _ = fmt.Fprintf(os.Stderr, "runtime: %+v\n%s\n", ri, real)
os.Exit(1)
}
func slash(str string) string {
if runtime.GOOS == "windows" {
return strings.ReplaceAll(str, "/", "\\")
}
return str
}

Loading…
Cancel
Save