Browse Source

Added update command

pull/103/head
Unknown 11 years ago
parent
commit
98f542c157
  1. 260
      cmd/update.go
  2. 14
      doc/conf.go
  3. 4
      gopm.go

260
cmd/update.go

@ -15,13 +15,14 @@
package cmd package cmd
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http"
"os" "os"
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
@ -32,160 +33,175 @@ import (
var CmdUpdate = cli.Command{ var CmdUpdate = cli.Command{
Name: "update", Name: "update",
Usage: "update self", Usage: "check and update gopm resources including itself",
Description: `Command bin downloads and links dependencies according to gopmfile, Description: `Command update checks updates of resources and gopm itself.
and build executable binary to work directory
gopm update gopm update
Can only specify one each time, and only works for projects that Resources will be updated automatically after executed this command,
contains main package`, but you have to confirm before updaing gopm itself.`,
Action: runUpdate, Action: runUpdate,
Flags: []cli.Flag{
cli.BoolFlag{"verbose, v", "show process details"},
},
} }
func exePath() string { func exePath() string {
file, _ := exec.LookPath(os.Args[0]) file, err := exec.LookPath(os.Args[0])
path, _ := filepath.Abs(file) if err != nil {
log.Error("Update", "Fail to execute exec.LookPath")
log.Fatal("", err.Error())
}
path, err := filepath.Abs(file)
if err != nil {
log.Error("Update", "Fail to get absolutely path")
log.Fatal("", err.Error())
}
return path return path
} }
func runUpdate(ctx *cli.Context) { type version struct {
doc.LoadPkgNameList(doc.HomeDir + "/data/pkgname.list") Gopm int
PackageNameList int `json:"package_name_list"`
}
installRepoPath = doc.HomeDir + "/repos" func runUpdate(ctx *cli.Context) {
setup(ctx)
// Check arguments. isAnythingUpdated := false
num := 0 // Load local version info.
localVerInfo := loadLocalVerInfo()
if len(ctx.Args()) != num { // Get remote version info.
log.Error("Update", "Fail to start command") var remoteVerInfo version
log.Fatal("", "Invalid argument number") if err := com.HttpGetJSON(http.DefaultClient, "http://gopm.io/VERSION.json", &remoteVerInfo); err != nil {
log.Error("Update", "Fail to fetch VERSION.json")
log.Fatal("", err.Error())
} }
// Parse package version. // Package name list.
info := "github.com/gpmgo/gopm" if remoteVerInfo.PackageNameList > localVerInfo.PackageNameList {
pkgPath := info log.Log("Updating pkgname.list...%v > %v",
ver := "" localVerInfo.PackageNameList, remoteVerInfo.PackageNameList)
var err error data, err := com.HttpGetBytes(http.DefaultClient, "https://raw2.github.com/gpmgo/docs/master/pkgname.list", nil)
if i := strings.Index(info, "@"); i > -1 { if err != nil {
pkgPath = info[:i] log.Error("Update", "Fail to update pkgname.list")
_, ver = validPath(info[i+1:]) log.Fatal("", err.Error())
}
_, err = com.SaveFile(path.Join(doc.HomeDir, doc.PKG_NAME_LIST_PATH), data)
if err != nil {
log.Error("Update", "Fail to save pkgname.list")
log.Fatal("", err.Error())
}
log.Log("Update pkgname.list to %v succeed!", remoteVerInfo.PackageNameList)
isAnythingUpdated = true
} }
// Check package name. // Gopm.
if !strings.Contains(pkgPath, "/") { if remoteVerInfo.Gopm > localVerInfo.Gopm {
name, ok := doc.PackageNameList[pkgPath] log.Log("Updating gopm...%v > %v",
if !ok { localVerInfo.Gopm, remoteVerInfo.Gopm)
log.Error("Update", "Invalid package name: "+pkgPath) installRepoPath = doc.HomeDir + "/repos"
log.Fatal("", "No match in the package name list")
tmpDirPath := path.Join(doc.HomeDir, "temp")
tmpBinPath := path.Join(tmpDirPath, "gopm")
if runtime.GOOS == "windows" {
tmpBinPath += ".exe"
} }
pkgPath = name
}
// Get code. os.MkdirAll(tmpDirPath, os.ModePerm)
stdout, _, _ := com.ExecCmd("gopm", "get", info) os.Remove(tmpBinPath)
if len(stdout) > 0 { // Fetch code.
fmt.Print(stdout) stdout, stderr, err := com.ExecCmd("gopm", "bin", "-u", "-d",
} "github.com/gpmgo/gopm", tmpDirPath)
if err != nil {
log.Error("Update", "Fail to execute 'gopm bin -u -d github.com/gpmgo/gopm "+tmpDirPath+"'")
log.Fatal("", err.Error())
}
if len(stderr) > 0 {
fmt.Print(stderr)
}
if len(stdout) > 0 {
fmt.Print(stdout)
}
// Check if previous steps were successful. // Check if previous steps were successful.
repoPath := installRepoPath + "/" + pkgPath if !com.IsExist(tmpBinPath) {
if len(ver) > 0 { log.Error("Update", "Fail to continue command")
repoPath += "." + ver log.Fatal("", "Previous steps weren't successful, no binary produced")
} }
if !com.IsDir(repoPath) {
log.Error("Bin", "Fail to continue command") movePath := exePath()
log.Fatal("", "Previous steps weren't successful") log.Log("New binary will be replaced for %s", movePath)
// Move binary to given directory.
if runtime.GOOS != "windows" {
err := os.Rename(tmpBinPath, movePath)
if err != nil {
log.Error("Update", "Fail to move binary")
log.Fatal("", err.Error())
}
os.Chmod(movePath+"/"+path.Base(tmpBinPath), os.ModePerm)
} else {
batPath := filepath.Join(workDir, "a.bat")
f, err := os.Create(batPath)
if err != nil {
log.Error("Update", "Fail to generate bat file")
log.Fatal("", err.Error())
}
f.WriteString(fmt.Sprintf(`ping -n 1 127.0.0.1>nul\ncopy "%v" "%v"\ndel "%v"\ndel "%v"`,
tmpBinPath, movePath, tmpBinPath, batPath))
f.Close()
attr := &os.ProcAttr{
Dir: workDir,
Env: os.Environ(),
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
}
_, err = os.StartProcess(batPath, []string{"a.bat"}, attr)
if err != nil {
log.Error("Update", "Fail to start bat process")
log.Fatal("", err.Error())
}
}
log.Success("SUCC", "Update", "Command execute successfully!")
isAnythingUpdated = true
} }
wd, err := os.Getwd() // Save JSON.
f, err := os.Create(path.Join(doc.HomeDir, doc.VER_PATH))
if err != nil { if err != nil {
log.Error("Bin", "Fail to get work directory") log.Error("Update", "Fail to create VERSION.json")
log.Fatal("", err.Error()) log.Fatal("", err.Error())
} }
if err := json.NewEncoder(f).Encode(&remoteVerInfo); err != nil {
// Change to repository path. log.Error("Update", "Fail to encode VERSION.json")
log.Log("Changing work directory to %s", repoPath)
err = os.Chdir(repoPath)
if err != nil {
log.Error("Bin", "Fail to change work directory")
log.Fatal("", err.Error()) log.Fatal("", err.Error())
} }
// Build application. if !isAnythingUpdated {
stdout, _, _ = com.ExecCmd("gopm", "build") log.Log("Nothing need to be updated")
if len(stdout) > 0 {
fmt.Print(stdout)
}
defer func() {
// Clean files.
os.RemoveAll(path.Join(repoPath, doc.VENDOR))
}()
// Check if previous steps were successful.
if com.IsFile(doc.GOPM_FILE_NAME) {
log.Trace("Loading gopmfile...")
gf := doc.NewGopmfile(".")
var err error
pkgName, err = gf.GetValue("target", "path")
if err == nil {
log.Log("Target name: %s", pkgName)
}
} }
}
if len(pkgName) == 0 { func loadLocalVerInfo() (ver version) {
_, pkgName = filepath.Split(pkgPath) verPath := path.Join(doc.HomeDir, doc.VER_PATH)
}
binName := path.Base(pkgName) // First time run should not exist.
if runtime.GOOS == "windows" { if !com.IsExist(verPath) {
binName += ".exe" return ver
}
binPath := path.Join(doc.VENDOR, "src", pkgPath, binName)
if !com.IsFile(binPath) {
log.Error("Update", "Fail to continue command")
log.Fatal("", "Previous steps weren't successful or the project does not contain main package")
} }
movePath := exePath() f, err := os.Open(verPath)
fmt.Print(movePath) if err != nil {
log.Error("Update", "Fail to open VERSION.json")
// Move binary to given directory. log.Fatal("", err.Error())
if runtime.GOOS != "windows" {
err = os.Rename(binPath, movePath)
if err != nil {
log.Error("Update", "Fail to move binary")
log.Fatal("", err.Error())
}
os.Chmod(movePath+"/"+binName, os.ModePerm)
} else {
batPath := filepath.Join(wd, "a.bat")
f, err := os.Create(batPath)
if err != nil {
log.Error("Update", "Fail to generate bat file")
log.Fatal("", err.Error())
}
f.WriteString(fmt.Sprintf(`ping -n 1 127.0.0.1>nul\ncopy "%v" "%v"\ndel "%v"\ndel "%v"`,
binPath, movePath, binPath, batPath))
f.Close()
attr := &os.ProcAttr{
Dir: wd,
Env: os.Environ(),
//Files: []*os.File{nil, nil, nil},
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
}
_, err = os.StartProcess(batPath, []string{"a.bat"}, attr)
if err != nil {
log.Error("Update", "Fail to start bat process")
log.Fatal("", err.Error())
}
} }
log.Log("Changing work directory back to %s", wd) if err := json.NewDecoder(f).Decode(&ver); err != nil {
os.Chdir(wd) log.Error("Update", "Fail to decode VERSION.json")
log.Fatal("", err.Error())
log.Success("SUCC", "Update", "Command execute successfully!") }
return ver
} }

14
doc/conf.go

@ -27,8 +27,10 @@ import (
) )
const ( const (
GOPM_FILE_NAME = ".gopmfile" GOPM_FILE_NAME = ".gopmfile"
RawHomeDir = "~/.gopm" PKG_NAME_LIST_PATH = "data/pkgname.list"
VER_PATH = "data/VERSION.json"
RawHomeDir = "~/.gopm"
) )
var ( var (
@ -47,7 +49,7 @@ func init() {
HomeDir = strings.Replace(RawHomeDir, "~", hd, -1) HomeDir = strings.Replace(RawHomeDir, "~", hd, -1)
LoadLocalNodes() LoadLocalNodes()
LoadPkgNameList(HomeDir + "/data/pkgname.list") LoadPkgNameList(path.Join(HomeDir, PKG_NAME_LIST_PATH))
} }
// NewGopmfile loads gopmgile in given directory. // NewGopmfile loads gopmgile in given directory.
@ -78,9 +80,13 @@ func LoadPkgNameList(filePath string) {
} }
pkgs := strings.Split(string(data), "\n") pkgs := strings.Split(string(data), "\n")
for _, line := range pkgs { for i, line := range pkgs {
infos := strings.Split(line, "=") infos := strings.Split(line, "=")
if len(infos) != 2 { if len(infos) != 2 {
// Last item might be empty line.
if i == len(pkgs)-1 {
continue
}
log.Error("", "Fail to parse package name: "+line) log.Error("", "Fail to parse package name: "+line)
log.Fatal("", "Invalid package name information") log.Fatal("", "Invalid package name information")
} }

4
gopm.go

@ -29,7 +29,7 @@ import (
// Test that go1.1 tag above is included in builds. main.go refers to this definition. // Test that go1.1 tag above is included in builds. main.go refers to this definition.
const go11tag = true const go11tag = true
const APP_VER = "0.6.1.0110" const APP_VER = "0.6.2.0113"
// //cmd.CmdSearch, // //cmd.CmdSearch,
// cmdClean, // cmdClean,
@ -57,7 +57,7 @@ func main() {
cmd.CmdRun, cmd.CmdRun,
cmd.CmdBuild, cmd.CmdBuild,
cmd.CmdInstall, cmd.CmdInstall,
//cmd.CmdUpdate, cmd.CmdUpdate,
//cmd.CmdTest, //cmd.CmdTest,
} }
app.Flags = append(app.Flags, []cli.Flag{ app.Flags = append(app.Flags, []cli.Flag{

Loading…
Cancel
Save