♻️ 引入 Gulu 工具库
This commit is contained in:
parent
1405d7482a
commit
4930408b17
27
conf/wide.go
27
conf/wide.go
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
// Copyright (c) 2014-present, b3gulu.Log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -27,9 +27,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/event"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -69,7 +68,7 @@ type conf struct {
|
|||
}
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// Wide configurations.
|
||||
var Wide *conf
|
||||
|
@ -91,7 +90,7 @@ func Load(confPath, confData, confServer, confLogLevel string, confSiteStatCode
|
|||
cmd := exec.Command("docker", "version")
|
||||
_, err := cmd.CombinedOutput()
|
||||
if nil != err {
|
||||
if !util.OS.IsWindows() {
|
||||
if !gulu.OS.IsWindows() {
|
||||
logger.Errorf("Not found 'docker' installed, running user's code will cause security problem")
|
||||
|
||||
os.Exit(-1)
|
||||
|
@ -179,16 +178,16 @@ func initWide(confPath, confData, confServer, confLogLevel string, confSiteStatC
|
|||
Wide.Autocomplete = true // default to true
|
||||
|
||||
// Logging Level
|
||||
log.SetLevel(Wide.LogLevel)
|
||||
gulu.Log.SetLevel(Wide.LogLevel)
|
||||
if "" != confLogLevel {
|
||||
Wide.LogLevel = confLogLevel
|
||||
log.SetLevel(confLogLevel)
|
||||
gulu.Log.SetLevel(confLogLevel)
|
||||
}
|
||||
|
||||
logger.Debug("Conf: \n" + string(bytes))
|
||||
|
||||
// User Home
|
||||
home, err := util.OS.Home()
|
||||
home, err := gulu.OS.Home()
|
||||
if nil != err {
|
||||
logger.Error("Can't get user's home, please report this issue to developer", err)
|
||||
|
||||
|
@ -241,14 +240,14 @@ func FixedTimeCheckEnv() {
|
|||
checkEnv() // check immediately
|
||||
|
||||
go func() {
|
||||
for _ = range time.Tick(time.Minute * 7) {
|
||||
for _ = range time.Tick(time.Minute*7) {
|
||||
checkEnv()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func checkEnv() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
cmd := exec.Command("go", "version")
|
||||
buf, err := cmd.CombinedOutput()
|
||||
|
@ -265,7 +264,7 @@ func checkEnv() {
|
|||
os.Exit(-1)
|
||||
}
|
||||
|
||||
gocode := util.Go.GetExecutableInGOBIN("gocode")
|
||||
gocode := gulu.Go.GetExecutableInGOBIN("gocode")
|
||||
cmd = exec.Command(gocode)
|
||||
_, err = cmd.Output()
|
||||
if nil != err {
|
||||
|
@ -274,7 +273,7 @@ func checkEnv() {
|
|||
logger.Warnf("Not found gocode [%s], please install it with this command: go get github.com/nsf/gocode", gocode)
|
||||
}
|
||||
|
||||
ideStub := util.Go.GetExecutableInGOBIN("gotools")
|
||||
ideStub := gulu.Go.GetExecutableInGOBIN("gotools")
|
||||
cmd = exec.Command(ideStub, "version")
|
||||
_, err = cmd.Output()
|
||||
if nil != err {
|
||||
|
@ -303,7 +302,7 @@ func GetGoFmt(userId string) string {
|
|||
case "gofmt":
|
||||
return "gofmt"
|
||||
case "goimports":
|
||||
return util.Go.GetExecutableInGOBIN("goimports")
|
||||
return gulu.Go.GetExecutableInGOBIN("goimports")
|
||||
default:
|
||||
logger.Errorf("Unsupported Go Format tool [%s]", user.GoFormat)
|
||||
return "gofmt"
|
||||
|
@ -413,7 +412,7 @@ func CreateWorkspaceDir(path string) {
|
|||
|
||||
// createDir creates a directory on the path if it not exists.
|
||||
func createDir(path string) {
|
||||
if !util.File.IsExist(path) {
|
||||
if !gulu.File.IsExist(path) {
|
||||
if err := os.MkdirAll(path, 0775); nil != err {
|
||||
logger.Error(err)
|
||||
|
||||
|
|
|
@ -27,16 +27,16 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/file"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// WSHandler handles request of creating editor channel.
|
||||
// XXX: NOT used at present
|
||||
|
@ -77,7 +77,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
logger.Tracef("offset: %d", offset)
|
||||
|
||||
gocode := util.Go.GetExecutableInGOBIN("gocode")
|
||||
gocode := gulu.Go.GetExecutableInGOBIN("gocode")
|
||||
argv := []string{"-f=json", "autocomplete", strconv.Itoa(offset)}
|
||||
|
||||
var output bytes.Buffer
|
||||
|
@ -159,7 +159,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
logger.Tracef("gocode set lib-path [%s]", libPath)
|
||||
|
||||
// FIXME: using gocode set lib-path has some issues while accrossing workspaces
|
||||
gocode := util.Go.GetExecutableInGOBIN("gocode")
|
||||
gocode := gulu.Go.GetExecutableInGOBIN("gocode")
|
||||
exec.Command(gocode, []string{"set", "lib-path", libPath}...).Run()
|
||||
|
||||
argv := []string{"-f=json", "--in=" + path, "autocomplete", strconv.Itoa(offset)}
|
||||
|
@ -179,8 +179,8 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// GetExprInfoHandler handles request of getting expression infomation.
|
||||
func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
session, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
uid := session.Values["uid"].(string)
|
||||
|
@ -223,7 +223,7 @@ func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
logger.Tracef("offset [%d]", offset)
|
||||
|
||||
ideStub := util.Go.GetExecutableInGOBIN("gotools")
|
||||
ideStub := gulu.Go.GetExecutableInGOBIN("gotools")
|
||||
argv := []string{"types", "-pos", filename + ":" + strconv.Itoa(offset), "-info", "."}
|
||||
cmd := exec.Command(ideStub, argv...)
|
||||
cmd.Dir = curDir
|
||||
|
@ -250,8 +250,8 @@ func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// FindDeclarationHandler handles request of finding declaration.
|
||||
func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
session, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if session.IsNew {
|
||||
|
@ -299,7 +299,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
logger.Tracef("offset [%d]", offset)
|
||||
|
||||
ideStub := util.Go.GetExecutableInGOBIN("gotools")
|
||||
ideStub := gulu.Go.GetExecutableInGOBIN("gotools")
|
||||
argv := []string{"types", "-pos", filename + ":" + strconv.Itoa(offset), "-def", "."}
|
||||
cmd := exec.Command(ideStub, argv...)
|
||||
cmd.Dir = curDir
|
||||
|
@ -338,8 +338,8 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// FindUsagesHandler handles request of finding usages.
|
||||
func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
session, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if session.IsNew {
|
||||
|
@ -387,7 +387,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
offset := getCursorOffset(code, line, ch)
|
||||
logger.Tracef("offset [%d]", offset)
|
||||
|
||||
ideStub := util.Go.GetExecutableInGOBIN("gotools")
|
||||
ideStub := gulu.Go.GetExecutableInGOBIN("gotools")
|
||||
argv := []string{"types", "-pos", filename + ":" + strconv.Itoa(offset), "-use", "."}
|
||||
cmd := exec.Command(ideStub, argv...)
|
||||
cmd.Dir = curDir
|
||||
|
|
|
@ -20,9 +20,9 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// GoFmtHandler handles request of formatting Go source code.
|
||||
|
@ -31,8 +31,8 @@ import (
|
|||
// 1. gofmt
|
||||
// 2. goimports
|
||||
func GoFmtHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
session, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if session.IsNew {
|
||||
|
@ -53,7 +53,7 @@ func GoFmtHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
filePath := args["file"].(string)
|
||||
|
||||
if util.Go.IsAPI(filePath) {
|
||||
if gulu.Go.IsAPI(filePath) {
|
||||
result.Succ = false
|
||||
|
||||
return
|
||||
|
|
|
@ -18,8 +18,7 @@ package event
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/b3log/gulu"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -39,7 +38,7 @@ const (
|
|||
const maxQueueLength = 10
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// Event represents an event.
|
||||
type Event struct {
|
||||
|
@ -70,7 +69,7 @@ var UserEventQueues = queues{}
|
|||
// Load initializes the event handling.
|
||||
func Load() {
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for event := range EventQueue {
|
||||
logger.Debugf("Received a global event [code=%d]", event.Code)
|
||||
|
@ -107,7 +106,7 @@ func (ueqs queues) New(sid string) *UserEventQueue {
|
|||
ueqs[sid] = q
|
||||
|
||||
go func() { // start listening
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for evt := range q.Queue {
|
||||
logger.Debugf("Session [%s] received an event [%d]", sid, evt.Code)
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/b3log/gulu"
|
||||
)
|
||||
|
||||
// GetZipHandler handles request of retrieving zip file.
|
||||
|
@ -34,7 +34,7 @@ func GetZipHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if !util.File.IsExist(path) {
|
||||
if !gulu.File.IsExist(path) {
|
||||
http.Error(w, "Not Found", 404)
|
||||
|
||||
return
|
||||
|
@ -51,8 +51,8 @@ func GetZipHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// CreateZipHandler handles request of creating zip.
|
||||
func CreateZipHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := util.NewResult()
|
||||
defer util.RetResult(w, r, data)
|
||||
data := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, data)
|
||||
|
||||
var args map[string]interface{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||
|
@ -75,7 +75,7 @@ func CreateZipHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
dir := filepath.Dir(path)
|
||||
|
||||
if !util.File.IsExist(path) {
|
||||
if !gulu.File.IsExist(path) {
|
||||
data.Succ = false
|
||||
data.Msg = "Can't find file [" + path + "]"
|
||||
|
||||
|
@ -83,7 +83,7 @@ func CreateZipHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
zipPath := filepath.Join(dir, name)
|
||||
zipFile, err := util.Zip.Create(zipPath + ".zip")
|
||||
zipFile, err := gulu.Zip.Create(zipPath + ".zip")
|
||||
if nil != err {
|
||||
logger.Error(err)
|
||||
data.Succ = false
|
||||
|
@ -92,7 +92,7 @@ func CreateZipHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
defer zipFile.Close()
|
||||
|
||||
if util.File.IsDir(path) {
|
||||
if gulu.File.IsDir(path) {
|
||||
zipFile.AddDirectory(base, path)
|
||||
} else {
|
||||
zipFile.AddEntry(base, path)
|
||||
|
|
|
@ -24,15 +24,14 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/event"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// Node represents a file node in file tree.
|
||||
type Node struct {
|
||||
|
@ -61,7 +60,7 @@ var apiNode *Node
|
|||
|
||||
// initAPINode builds the Go API file node.
|
||||
func initAPINode() {
|
||||
apiPath := util.Go.GetAPIPath()
|
||||
apiPath := gulu.Go.GetAPIPath()
|
||||
|
||||
apiNode = &Node{Name: "Go API", Path: apiPath, IconSkin: "ico-ztree-dir-api ", Type: "d",
|
||||
Creatable: false, Removable: false, IsGoAPI: true, Children: []*Node{}}
|
||||
|
@ -82,8 +81,8 @@ func GetFilesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
uid := httpSession.Values["uid"].(string)
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetGzResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetGzResult(w, r, result)
|
||||
|
||||
userWorkspace := conf.GetUserWorkspace(uid)
|
||||
workspaces := filepath.SplitList(userWorkspace)
|
||||
|
@ -134,7 +133,7 @@ func RefreshDirectoryHandler(w http.ResponseWriter, r *http.Request) {
|
|||
r.ParseForm()
|
||||
path := r.FormValue("path")
|
||||
|
||||
if !util.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||
if !gulu.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -164,8 +163,8 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
uid := httpSession.Values["uid"].(string)
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -178,13 +177,13 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
path := args["path"].(string)
|
||||
|
||||
if !util.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||
if !gulu.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
size := util.File.GetFileSize(path)
|
||||
size := gulu.File.GetFileSize(path)
|
||||
if size > 5242880 { // 5M
|
||||
result.Succ = false
|
||||
result.Msg = "This file is too large to open :("
|
||||
|
@ -199,7 +198,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
extension := filepath.Ext(path)
|
||||
|
||||
if util.File.IsImg(extension) {
|
||||
if gulu.File.IsImg(extension) {
|
||||
// image file will be open in a browser tab
|
||||
|
||||
data["mode"] = "img"
|
||||
|
@ -221,7 +220,7 @@ func GetFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
content := string(buf)
|
||||
|
||||
if util.File.IsBinary(content) {
|
||||
if gulu.File.IsBinary(content) {
|
||||
result.Succ = false
|
||||
result.Msg = "Can't open a binary file :("
|
||||
} else {
|
||||
|
@ -240,8 +239,8 @@ func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
uid := httpSession.Values["uid"].(string)
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -255,7 +254,7 @@ func SaveFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
filePath := args["file"].(string)
|
||||
sid := args["sid"].(string)
|
||||
|
||||
if util.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||
if gulu.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -296,8 +295,8 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
uid := httpSession.Values["uid"].(string)
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -310,7 +309,7 @@ func NewFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
path := args["path"].(string)
|
||||
|
||||
if util.Go.IsAPI(path) || !session.CanAccess(uid, path) {
|
||||
if gulu.Go.IsAPI(path) || !session.CanAccess(uid, path) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -348,8 +347,8 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
uid := httpSession.Values["uid"].(string)
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -362,7 +361,7 @@ func RemoveFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
path := args["path"].(string)
|
||||
|
||||
if util.Go.IsAPI(path) || !session.CanAccess(uid, path) {
|
||||
if gulu.Go.IsAPI(path) || !session.CanAccess(uid, path) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -394,8 +393,8 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
uid := httpSession.Values["uid"].(string)
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -407,7 +406,7 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
oldPath := args["oldPath"].(string)
|
||||
if util.Go.IsAPI(oldPath) ||
|
||||
if gulu.Go.IsAPI(oldPath) ||
|
||||
!session.CanAccess(uid, oldPath) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
|
@ -415,7 +414,7 @@ func RenameFileHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
newPath := args["newPath"].(string)
|
||||
if util.Go.IsAPI(newPath) || !session.CanAccess(uid, newPath) {
|
||||
if gulu.Go.IsAPI(newPath) || !session.CanAccess(uid, newPath) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -459,8 +458,8 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
uid := httpSession.Values["uid"].(string)
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||
|
@ -471,7 +470,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
path := args["path"].(string) // path of selected file in file tree
|
||||
if !util.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||
if !gulu.Go.IsAPI(path) && !session.CanAccess(uid, path) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -482,7 +481,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
|
|||
userWorkspace := conf.GetUserWorkspace(uid)
|
||||
workspaces := filepath.SplitList(userWorkspace)
|
||||
|
||||
if "" != path && !util.File.IsDir(path) {
|
||||
if "" != path && !gulu.File.IsDir(path) {
|
||||
path = filepath.Dir(path)
|
||||
}
|
||||
|
||||
|
@ -492,7 +491,7 @@ func FindHandler(w http.ResponseWriter, r *http.Request) {
|
|||
rs := find(workspace+conf.PathSeparator+"src", name, []*string{})
|
||||
|
||||
for _, r := range rs {
|
||||
substr := util.Str.LCS(path, *r)
|
||||
substr := gulu.Str.LCS(path, *r)
|
||||
|
||||
founds = append(founds, &foundPath{Path: filepath.ToSlash(*r), score: len(substr)})
|
||||
}
|
||||
|
@ -512,8 +511,8 @@ func SearchTextHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -545,7 +544,7 @@ func SearchTextHandler(w http.ResponseWriter, r *http.Request) {
|
|||
text := args["text"].(string)
|
||||
|
||||
founds := []*Snippet{}
|
||||
if util.File.IsDir(dir) {
|
||||
if gulu.File.IsDir(dir) {
|
||||
founds = search(dir, extension, text, []*Snippet{})
|
||||
} else {
|
||||
founds = searchInFile(dir, text)
|
||||
|
@ -644,7 +643,7 @@ func listFiles(dirname string) []string {
|
|||
//
|
||||
// Refers to the zTree document for CSS class names.
|
||||
func getIconSkin(filenameExtension string) string {
|
||||
if util.File.IsImg(filenameExtension) {
|
||||
if gulu.File.IsImg(filenameExtension) {
|
||||
return "ico-ztree-img "
|
||||
}
|
||||
|
||||
|
@ -763,7 +762,7 @@ func find(dir, name string, results []*string) []*string {
|
|||
path := dir + fname
|
||||
|
||||
if fileInfo.IsDir() {
|
||||
if util.Str.Contains(fname, defaultExcludesFind) {
|
||||
if gulu.Str.Contains(fname, defaultExcludesFind) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -836,7 +835,7 @@ func searchInFile(path string, text string) []*Snippet {
|
|||
}
|
||||
|
||||
content := string(bytes)
|
||||
if util.File.IsBinary(content) {
|
||||
if gulu.File.IsBinary(content) {
|
||||
return ret
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/b3log/gulu"
|
||||
)
|
||||
|
||||
type element struct {
|
||||
|
@ -34,8 +34,8 @@ type element struct {
|
|||
|
||||
// GetOutlineHandler gets outfile of a go file.
|
||||
func GetOutlineHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
|
9
go.mod
9
go.mod
|
@ -3,6 +3,7 @@ module github.com/b3log/wide
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/b3log/gulu v0.0.0-20190524125155-0ed03084217c
|
||||
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f // indirect
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.7
|
||||
|
@ -10,12 +11,12 @@ require (
|
|||
github.com/gorilla/securecookie v0.0.0-20150327155805-8e98dd730fc4 // indirect
|
||||
github.com/gorilla/sessions v0.0.0-20150417174705-f61c3ec2cf65
|
||||
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a
|
||||
github.com/hashicorp/go-version v1.2.0
|
||||
github.com/moul/http2curl v1.0.0 // indirect
|
||||
github.com/parnurzeal/gorequest v0.2.15
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204 // indirect
|
||||
golang.org/x/sys v0.0.0-20190515190549-87c872767d25 // indirect
|
||||
golang.org/x/text v0.3.2
|
||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f // indirect
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 // indirect
|
||||
golang.org/x/sys v0.0.0-20190524122548-abf6ff778158 // indirect
|
||||
golang.org/x/tools v0.0.0-20190523174634-38d8bcfa38af // indirect
|
||||
)
|
||||
|
|
14
go.sum
14
go.sum
|
@ -1,3 +1,7 @@
|
|||
github.com/b3log/gulu v0.0.0-20190524124046-926f105c6dd8 h1:Ir8QVO1dwv6MEdkAE7L1oS5bJheb0Dr+AYmBXskQPF0=
|
||||
github.com/b3log/gulu v0.0.0-20190524124046-926f105c6dd8/go.mod h1:UmyB0pe8jv1K3dZy/4UE3uCpM8zYkB4nbiIgjemuQ7A=
|
||||
github.com/b3log/gulu v0.0.0-20190524125155-0ed03084217c h1:1+Pr5/IUfYBTiZVyzX7CfdkLVtL+LZa5yrxhjLlPYXY=
|
||||
github.com/b3log/gulu v0.0.0-20190524125155-0ed03084217c/go.mod h1:UmyB0pe8jv1K3dZy/4UE3uCpM8zYkB4nbiIgjemuQ7A=
|
||||
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs=
|
||||
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f h1:AUj1VoZUfhPhOPHULCQQDnGhRelpFWHMLhQVWDsS0v4=
|
||||
|
@ -14,8 +18,6 @@ github.com/gorilla/sessions v0.0.0-20150417174705-f61c3ec2cf65 h1:bDPV+Nh80WIp0U
|
|||
github.com/gorilla/sessions v0.0.0-20150417174705-f61c3ec2cf65/go.mod h1:+WVp8kdw6VhyKExm03PAMRn2ZxnPtm58pV0dBVPdhHE=
|
||||
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a h1:p/PGT+3UGSK7eULOGHUMCUxI5U976R34HWuKHbFpK3Q=
|
||||
github.com/gorilla/websocket v0.0.0-20150530030352-a3ec486e6a7a/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
|
||||
|
@ -30,14 +32,22 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
|
|||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204 h1:4yG6GqBtw9C+UrLp6s2wtSniayy/Vd/3F7ffLE427XI=
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190515190549-87c872767d25 h1:SSKQq5sjDoW0L0NaDoVl7d7HmtTxM0ezm0Ef9azs4uQ=
|
||||
golang.org/x/sys v0.0.0-20190515190549-87c872767d25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190523174634-38d8bcfa38af/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
|
|
|
@ -22,11 +22,11 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/gulu"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// Locale.
|
||||
type locale struct {
|
||||
|
|
217
log/logs.go
217
log/logs.go
|
@ -1,217 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package log includes logging related manipulations.
|
||||
//
|
||||
// log.SetLevel("debug")
|
||||
// logger := log.NewLogger(os.Stdout)
|
||||
//
|
||||
// logger.Trace("trace message)
|
||||
// logger.Debug("debug message")
|
||||
// logger.Info("info message")
|
||||
// logger.Warn("warning message")
|
||||
// logger.Error("error message")
|
||||
//
|
||||
// logger.Errorf("formatted %s message", "error")
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
stdlog "log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Logging level.
|
||||
const (
|
||||
Off = iota
|
||||
Trace
|
||||
Debug
|
||||
Info
|
||||
Warn
|
||||
Error
|
||||
)
|
||||
|
||||
// all loggers.
|
||||
var loggers []*Logger
|
||||
|
||||
// the global default logging level, it will be used for creating logger.
|
||||
var logLevel = Debug
|
||||
|
||||
// Logger represents a simple logger with level.
|
||||
// The underlying logger is the standard Go logging "log".
|
||||
type Logger struct {
|
||||
level int
|
||||
logger *stdlog.Logger
|
||||
}
|
||||
|
||||
// NewLogger creates a logger.
|
||||
func NewLogger(out io.Writer) *Logger {
|
||||
ret := &Logger{level: logLevel, logger: stdlog.New(out, "", stdlog.Ldate|stdlog.Ltime|stdlog.Lshortfile)}
|
||||
|
||||
loggers = append(loggers, ret)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// SetLevel sets the logging level of all loggers.
|
||||
func SetLevel(level string) {
|
||||
logLevel = getLevel(level)
|
||||
|
||||
for _, l := range loggers {
|
||||
l.SetLevel(level)
|
||||
}
|
||||
}
|
||||
|
||||
// getLevel gets logging level int value corresponding to the specified level.
|
||||
func getLevel(level string) int {
|
||||
level = strings.ToLower(level)
|
||||
|
||||
switch level {
|
||||
case "off":
|
||||
return Off
|
||||
case "trace":
|
||||
return Trace
|
||||
case "debug":
|
||||
return Debug
|
||||
case "info":
|
||||
return Info
|
||||
case "warn":
|
||||
return Warn
|
||||
case "error":
|
||||
return Error
|
||||
default:
|
||||
return Info
|
||||
}
|
||||
}
|
||||
|
||||
// SetLevel sets the logging level of a logger.
|
||||
func (l *Logger) SetLevel(level string) {
|
||||
l.level = getLevel(level)
|
||||
}
|
||||
|
||||
// IsTraceEnabled determines whether the trace level is enabled.
|
||||
func (l *Logger) IsTraceEnabled() bool {
|
||||
return l.level <= Trace
|
||||
}
|
||||
|
||||
// IsDebugEnabled determines whether the debug level is enabled.
|
||||
func (l *Logger) IsDebugEnabled() bool {
|
||||
return l.level <= Debug
|
||||
}
|
||||
|
||||
// IsWarnEnabled determines whether the debug level is enabled.
|
||||
func (l *Logger) IsWarnEnabled() bool {
|
||||
return l.level <= Warn
|
||||
}
|
||||
|
||||
// Trace prints trace level message.
|
||||
func (l *Logger) Trace(v ...interface{}) {
|
||||
if Trace < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("T ")
|
||||
l.logger.Output(2, fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Tracef prints trace level message with format.
|
||||
func (l *Logger) Tracef(format string, v ...interface{}) {
|
||||
if Trace < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("T ")
|
||||
l.logger.Output(2, fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Debug prints debug level message.
|
||||
func (l *Logger) Debug(v ...interface{}) {
|
||||
if Debug < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("D ")
|
||||
l.logger.Output(2, fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Debugf prints debug level message with format.
|
||||
func (l *Logger) Debugf(format string, v ...interface{}) {
|
||||
if Debug < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("D ")
|
||||
l.logger.Output(2, fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Info prints info level message.
|
||||
func (l *Logger) Info(v ...interface{}) {
|
||||
if Info < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("I ")
|
||||
l.logger.Output(2, fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Infof prints info level message with format.
|
||||
func (l *Logger) Infof(format string, v ...interface{}) {
|
||||
if Info < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("I ")
|
||||
l.logger.Output(2, fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Warn prints warning level message.
|
||||
func (l *Logger) Warn(v ...interface{}) {
|
||||
if Warn < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("W ")
|
||||
l.logger.Output(2, fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Warn prints warning level message with format.
|
||||
func (l *Logger) Warnf(format string, v ...interface{}) {
|
||||
if Warn < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("W ")
|
||||
l.logger.Output(2, fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Error prints error level message.
|
||||
func (l *Logger) Error(v ...interface{}) {
|
||||
if Error < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("E ")
|
||||
l.logger.Output(2, fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Errorf prints error level message with format.
|
||||
func (l *Logger) Errorf(format string, v ...interface{}) {
|
||||
if Error < l.level {
|
||||
return
|
||||
}
|
||||
|
||||
l.logger.SetPrefix("E ")
|
||||
l.logger.Output(2, fmt.Sprintf(format, v...))
|
||||
}
|
169
log/logs_test.go
169
log/logs_test.go
|
@ -1,169 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var logger = NewLogger(os.Stdout)
|
||||
|
||||
func TestSetLevel(t *testing.T) {
|
||||
SetLevel("trace")
|
||||
}
|
||||
|
||||
func TestTrace(t *testing.T) {
|
||||
logger.SetLevel("trace")
|
||||
logger.Trace("trace")
|
||||
logger.SetLevel("off")
|
||||
logger.Trace("trace")
|
||||
}
|
||||
|
||||
func TestTracef(t *testing.T) {
|
||||
logger.SetLevel("trace")
|
||||
logger.Tracef("tracef")
|
||||
logger.SetLevel("off")
|
||||
logger.Tracef("tracef")
|
||||
}
|
||||
|
||||
func TestDebug(t *testing.T) {
|
||||
logger.SetLevel("debug")
|
||||
logger.Debug("debug")
|
||||
logger.SetLevel("off")
|
||||
logger.Debug("debug")
|
||||
}
|
||||
|
||||
func TestDebugf(t *testing.T) {
|
||||
logger.SetLevel("debug")
|
||||
logger.Debugf("debugf")
|
||||
logger.SetLevel("off")
|
||||
logger.Debug("debug")
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
logger.SetLevel("info")
|
||||
logger.Info("info")
|
||||
logger.SetLevel("off")
|
||||
logger.Info("info")
|
||||
}
|
||||
|
||||
func TestInfof(t *testing.T) {
|
||||
logger.SetLevel("info")
|
||||
logger.Infof("infof")
|
||||
logger.SetLevel("off")
|
||||
logger.Infof("infof")
|
||||
}
|
||||
|
||||
func TestWarn(t *testing.T) {
|
||||
logger.SetLevel("warn")
|
||||
logger.Warn("warn")
|
||||
logger.SetLevel("off")
|
||||
logger.Warn("warn")
|
||||
}
|
||||
|
||||
func TestWarnf(t *testing.T) {
|
||||
logger.SetLevel("warn")
|
||||
logger.Warnf("warnf")
|
||||
logger.SetLevel("off")
|
||||
logger.Warnf("warnf")
|
||||
}
|
||||
|
||||
func TestError(t *testing.T) {
|
||||
logger.SetLevel("error")
|
||||
logger.Error("error")
|
||||
logger.SetLevel("off")
|
||||
logger.Error("error")
|
||||
}
|
||||
|
||||
func TestErrorf(t *testing.T) {
|
||||
logger.SetLevel("error")
|
||||
logger.Errorf("errorf")
|
||||
logger.SetLevel("off")
|
||||
logger.Errorf("errorf")
|
||||
}
|
||||
|
||||
func TestGetLevel(t *testing.T) {
|
||||
if getLevel("trace") != Trace {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if getLevel("debug") != Debug {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if getLevel("info") != Info {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if getLevel("warn") != Warn {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if getLevel("error") != Error {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoggerSetLevel(t *testing.T) {
|
||||
logger.SetLevel("trace")
|
||||
|
||||
if logger.level != Trace {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsTraceEnabled(t *testing.T) {
|
||||
logger.SetLevel("trace")
|
||||
|
||||
if !logger.IsTraceEnabled() {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsDebugEnabled(t *testing.T) {
|
||||
logger.SetLevel("debug")
|
||||
|
||||
if !logger.IsDebugEnabled() {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsWarnEnabled(t *testing.T) {
|
||||
logger.SetLevel("warn")
|
||||
|
||||
if !logger.IsWarnEnabled() {
|
||||
t.FailNow()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
17
main.go
17
main.go
|
@ -29,21 +29,20 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/editor"
|
||||
"github.com/b3log/wide/event"
|
||||
"github.com/b3log/wide/file"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/notification"
|
||||
"github.com/b3log/wide/output"
|
||||
"github.com/b3log/wide/playground"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// Logger
|
||||
var logger *log.Logger
|
||||
var logger *gulu.Logger
|
||||
|
||||
// The only one init function in Wide.
|
||||
func init() {
|
||||
|
@ -55,10 +54,10 @@ func init() {
|
|||
|
||||
flag.Parse()
|
||||
|
||||
log.SetLevel("warn")
|
||||
logger = log.NewLogger(os.Stdout)
|
||||
gulu.Log.SetLevel("warn")
|
||||
logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
//wd := util.OS.Pwd()
|
||||
//wd := gulu.OS.Pwd()
|
||||
//if strings.HasPrefix(wd, os.TempDir()) {
|
||||
// logger.Error("Don't run Wide in OS' temp directory or with `go run`")
|
||||
//
|
||||
|
@ -74,7 +73,7 @@ func init() {
|
|||
session.FixedTimeRelease()
|
||||
session.FixedTimeReport()
|
||||
|
||||
logger.Debug("host ["+runtime.Version()+", "+runtime.GOOS+"_"+runtime.GOARCH+"], cross-compilation ", util.Go.GetCrossPlatforms())
|
||||
logger.Debug("host ["+runtime.Version()+", "+runtime.GOOS+"_"+runtime.GOARCH+"], cross-compilation ", gulu.Go.GetCrossPlatforms())
|
||||
}
|
||||
|
||||
// Main.
|
||||
|
@ -204,7 +203,7 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(locale), "locale": locale,
|
||||
"uid": uid, "sid": session.WideSessions.GenId(), "latestSessionContent": user.LatestSessionContent,
|
||||
"pathSeparator": conf.PathSeparator, "codeMirrorVer": conf.CodeMirrorVer,
|
||||
"user": user, "editorThemes": conf.GetEditorThemes(), "crossPlatforms": util.Go.GetCrossPlatforms()}
|
||||
"user": user, "editorThemes": conf.GetEditorThemes(), "crossPlatforms": gulu.Go.GetCrossPlatforms()}
|
||||
|
||||
logger.Debugf("User [%s] has [%d] sessions", uid, len(wideSessions))
|
||||
|
||||
|
@ -409,7 +408,7 @@ func stopwatch(handler func(w http.ResponseWriter, r *http.Request)) func(w http
|
|||
// panicRecover wraps the panic recover process.
|
||||
func panicRecover(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
handler(w, r)
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/event"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/gorilla/websocket"
|
||||
|
@ -40,7 +40,7 @@ const (
|
|||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// Notification represents a notification.
|
||||
type Notification struct {
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/b3log/gulu"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -30,13 +31,12 @@ import (
|
|||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// BuildHandler handles request of building.
|
||||
func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if httpSession.IsNew {
|
||||
|
@ -58,7 +58,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
sid := args["sid"].(string)
|
||||
filePath := args["file"].(string)
|
||||
if util.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||
if gulu.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -98,7 +98,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
var goModCmd *exec.Cmd
|
||||
if !util.File.IsExist(filepath.Join(curDir, "go.mod")) {
|
||||
if !gulu.File.IsExist(filepath.Join(curDir, "go.mod")) {
|
||||
curDirName := filepath.Base(curDir)
|
||||
goModCmd = exec.Command("go", "mod", "init", curDirName)
|
||||
} else {
|
||||
|
@ -118,7 +118,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
var goBuildArgs []string
|
||||
goBuildArgs = append(goBuildArgs, "build")
|
||||
goBuildArgs = append(goBuildArgs, user.BuildArgs(runtime.GOOS)...)
|
||||
if !util.Str.Contains("-i", goBuildArgs) {
|
||||
if !gulu.Str.Contains("-i", goBuildArgs) {
|
||||
goBuildArgs = append(goBuildArgs, "-i")
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
setCmdEnv(cmd, uid)
|
||||
|
||||
suffix := ""
|
||||
if util.OS.IsWindows() {
|
||||
if gulu.OS.IsWindows() {
|
||||
suffix = ".exe"
|
||||
}
|
||||
executable := filepath.Base(curDir) + suffix
|
||||
|
@ -167,7 +167,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
/////////
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for {
|
||||
wsChannel := session.OutputWS[sid]
|
||||
|
|
|
@ -26,16 +26,16 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// CrossCompilationHandler handles request of cross compilation.
|
||||
func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if httpSession.IsNew {
|
||||
|
@ -58,7 +58,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sid := args["sid"].(string)
|
||||
filePath := args["path"].(string)
|
||||
|
||||
if util.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||
if gulu.Go.IsAPI(filePath) || !session.CanAccess(uid, filePath) {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
|
||||
return
|
||||
|
@ -152,7 +152,7 @@ func CrossCompilationHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
go func(runningId int) {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
defer cmd.Wait()
|
||||
|
||||
// read all
|
||||
|
|
|
@ -26,16 +26,16 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// GoInstallHandler handles request of go install.
|
||||
func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if httpSession.IsNew {
|
||||
|
@ -116,7 +116,7 @@ func GoInstallHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
go func(runningId int) {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
defer cmd.Wait()
|
||||
|
||||
logger.Debugf("User [%s, %s] is running [go install] [id=%d, dir=%s]", uid, sid, runningId, curDir)
|
||||
|
|
|
@ -25,8 +25,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/gorilla/websocket"
|
||||
|
@ -38,7 +38,7 @@ const (
|
|||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// Lint represents a code lint.
|
||||
type Lint struct {
|
||||
|
@ -122,7 +122,7 @@ func setCmdEnv(cmd *exec.Cmd, uid string) {
|
|||
"GOCACHE="+cache,
|
||||
"PATH="+os.Getenv("PATH"))
|
||||
|
||||
if util.OS.IsWindows() {
|
||||
if gulu.OS.IsWindows() {
|
||||
// FIXME: for some weird issues on Windows, such as: The requested service provider could not be loaded or initialized.
|
||||
cmd.Env = append(cmd.Env, os.Environ()...)
|
||||
} else {
|
||||
|
|
|
@ -24,16 +24,16 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// GoTestHandler handles request of go test.
|
||||
func GoTestHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if httpSession.IsNew {
|
||||
|
@ -112,7 +112,7 @@ func GoTestHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
go func(runningId int) {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
logger.Debugf("User [%s, %s] is running [go test] [runningId=%d]", uid, sid, runningId)
|
||||
|
||||
|
|
|
@ -24,16 +24,16 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// GoVetHandler handles request of go vet.
|
||||
func GoVetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if httpSession.IsNew {
|
||||
|
@ -112,7 +112,7 @@ func GoVetHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
go func(runningId int) {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
logger.Debugf("User [%s, %s] is running [go vet] [runningId=%d]", uid, sid, runningId)
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// AutocompleteHandler handles request of code autocompletion.
|
||||
|
@ -51,7 +51,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
offset := getCursorOffset(code, line, ch)
|
||||
|
||||
argv := []string{"-f=json", "autocomplete", strconv.Itoa(offset)}
|
||||
gocode := util.Go.GetExecutableInGOBIN("gocode")
|
||||
gocode := gulu.Go.GetExecutableInGOBIN("gocode")
|
||||
cmd := exec.Command(gocode, argv...)
|
||||
|
||||
stdin, _ := cmd.StdinPipe()
|
||||
|
|
|
@ -22,15 +22,15 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// BuildHandler handles request of Playground building.
|
||||
func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if httpSession.IsNew {
|
||||
|
@ -51,7 +51,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
filePath := filepath.Clean(conf.Wide.Data + "/playground/" + fileName)
|
||||
|
||||
suffix := ""
|
||||
if util.OS.IsWindows() {
|
||||
if gulu.OS.IsWindows() {
|
||||
suffix = ".exe"
|
||||
}
|
||||
|
||||
|
|
|
@ -24,15 +24,15 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// SaveHandler handles request of Playground code save.
|
||||
func SaveHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
session, _ := session.HTTPSession.Get(r, session.CookieName)
|
||||
if session.IsNew {
|
||||
|
|
|
@ -26,16 +26,16 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
// IndexHandler handles request of Playground index.
|
||||
func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -59,7 +59,7 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
if strings.HasSuffix(r.URL.Path, ".go") {
|
||||
fileNameArg := r.URL.Path[len("/playground/"):]
|
||||
filePath := filepath.Clean(conf.Wide.Data+ "/playground/" + fileNameArg)
|
||||
filePath := filepath.Clean(conf.Wide.Data + "/playground/" + fileNameArg)
|
||||
|
||||
bytes, err := ioutil.ReadFile(filePath)
|
||||
if nil != err {
|
||||
|
|
|
@ -25,9 +25,9 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/parnurzeal/gorequest"
|
||||
)
|
||||
|
||||
|
@ -35,7 +35,7 @@ var states = map[string]string{}
|
|||
|
||||
// RedirectGitHubHandler redirects to GitHub auth page.
|
||||
func RedirectGitHubHandler(w http.ResponseWriter, r *http.Request) {
|
||||
requestResult := util.NewResult()
|
||||
requestResult := gulu.Ret.NewResult()
|
||||
_, _, errs := gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
|
||||
Get("https://hacpai.com/oauth/wide/client").
|
||||
Set("user-agent", conf.UserAgent).Timeout(10 * time.Second).EndStruct(requestResult)
|
||||
|
@ -57,7 +57,7 @@ func RedirectGitHubHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
state := r.URL.Query().Get("state")
|
||||
referer := conf.Wide.Server + "__" + state
|
||||
state = util.Rand.String(16) + referer
|
||||
state = gulu.Rand.String(16) + referer
|
||||
states[state] = state
|
||||
path := loginAuthURL + "?client_id=" + clientId + "&state=" + state + "&scope=public_repo,read:user,user:follow"
|
||||
http.Redirect(w, r, path, http.StatusSeeOther)
|
||||
|
@ -93,10 +93,10 @@ func GithubCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if nil == user {
|
||||
msg := addUser(githubId, userName, avatar)
|
||||
if userCreated != msg {
|
||||
result := util.NewResult()
|
||||
result := gulu.Ret.NewResult()
|
||||
result.Succ = false
|
||||
result.Msg = msg
|
||||
util.RetResult(w, r, result)
|
||||
gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -149,8 +149,8 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// LogoutHandler handles request of user logout (exit).
|
||||
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
httpSession, _ := HTTPSession.Get(r, CookieName)
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ package session
|
|||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/util"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -28,6 +26,10 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
// Type of process set.
|
||||
|
@ -43,8 +45,8 @@ var procMutex sync.Mutex
|
|||
|
||||
// RunHandler handles request of executing a binary file.
|
||||
func RunHandler(w http.ResponseWriter, r *http.Request, channel map[string]*util.WSChannel) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
|
@ -120,12 +122,12 @@ func RunHandler(w http.ResponseWriter, r *http.Request, channel map[string]*util
|
|||
}
|
||||
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
logger.Debugf("User [%s, %s] is running [id=%s, file=%s]", wSession.UserId, sid, rid, filePath)
|
||||
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for {
|
||||
r, _, err := outReader.ReadRune()
|
||||
|
@ -196,8 +198,8 @@ func RunHandler(w http.ResponseWriter, r *http.Request, channel map[string]*util
|
|||
|
||||
// StopHandler handles request of stopping a running process.
|
||||
func StopHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
var args map[string]interface{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||
|
|
|
@ -35,9 +35,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/event"
|
||||
"github.com/b3log/wide/log"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/gorilla/sessions"
|
||||
|
@ -52,7 +52,7 @@ const (
|
|||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
var logger = gulu.Log.NewLogger(os.Stdout)
|
||||
|
||||
var (
|
||||
// SessionWS holds all session channels. <sid, *util.WSChannel>
|
||||
|
@ -105,7 +105,7 @@ var mutex sync.Mutex
|
|||
// Invalid sessions: sessions that not used within 30 minutes, refers to WideSession.Updated field.
|
||||
func FixedTimeRelease() {
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for _ = range time.Tick(time.Hour) {
|
||||
hour, _ := time.ParseDuration("-30m")
|
||||
|
@ -139,9 +139,9 @@ func (u *userReport) report() string {
|
|||
// FixedTimeReport reports the Wide sessions status periodically (10 minutes).
|
||||
func FixedTimeReport() {
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for _ = range time.Tick(10*time.Minute) {
|
||||
for _ = range time.Tick(10 * time.Minute) {
|
||||
users := userReports{}
|
||||
processSum := 0
|
||||
|
||||
|
@ -284,8 +284,8 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// SaveContentHandler handles request of session content string.
|
||||
func SaveContentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
args := struct {
|
||||
Sid string
|
||||
|
@ -477,7 +477,7 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
|
|||
}
|
||||
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for {
|
||||
ch := SessionWS[sid]
|
||||
|
@ -500,7 +500,7 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
|
|||
if event.Op&fsnotify.Create == fsnotify.Create {
|
||||
fileType := "f"
|
||||
|
||||
if util.File.IsDir(path) {
|
||||
if gulu.File.IsDir(path) {
|
||||
fileType = "d"
|
||||
|
||||
if err = watcher.Add(path); nil != err {
|
||||
|
@ -526,7 +526,7 @@ func (sessions *wSessions) new(httpSession *sessions.Session, sid string) *WideS
|
|||
}()
|
||||
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
workspaces := filepath.SplitList(conf.GetUserWorkspace(uid))
|
||||
for _, workspace := range workspaces {
|
||||
|
|
|
@ -24,9 +24,9 @@ import (
|
|||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/gulu"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/i18n"
|
||||
"github.com/b3log/wide/util"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -67,7 +67,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(user.Locale), "user": user,
|
||||
"ver": conf.WideVersion, "goos": runtime.GOOS, "goarch": runtime.GOARCH, "gover": runtime.Version(),
|
||||
"locales": i18n.GetLocalesNames(), "gofmts": util.Go.GetGoFormats(),
|
||||
"locales": i18n.GetLocalesNames(), "gofmts": gulu.Go.GetGoFormats(),
|
||||
"themes": conf.GetThemes(), "editorThemes": conf.GetEditorThemes()}
|
||||
|
||||
t, err := template.ParseFiles("views/preference.html")
|
||||
|
@ -93,8 +93,8 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// non-GET request as save request
|
||||
|
||||
result := util.NewResult()
|
||||
defer util.RetResult(w, r, result)
|
||||
result := gulu.Ret.NewResult()
|
||||
defer gulu.Ret.RetResult(w, r, result)
|
||||
|
||||
args := struct {
|
||||
FontFamily string
|
||||
|
@ -154,7 +154,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// Main goal of this function is to save user session content, for restoring session content while user open Wide next time.
|
||||
func FixedTimeSave() {
|
||||
go func() {
|
||||
defer util.Recover()
|
||||
defer gulu.Panic.Recover()
|
||||
|
||||
for _ = range time.Tick(time.Minute) {
|
||||
SaveOnlineUsers()
|
||||
|
|
163
util/file.go
163
util/file.go
|
@ -1,163 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/b3log/wide/log"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var fileLogger = log.NewLogger(os.Stdout)
|
||||
|
||||
type myfile struct{}
|
||||
|
||||
// File utilities.
|
||||
var File = myfile{}
|
||||
|
||||
// GetFileSize get the length in bytes of file of the specified path.
|
||||
func (*myfile) GetFileSize(path string) int64 {
|
||||
fi, err := os.Stat(path)
|
||||
if nil != err {
|
||||
fileLogger.Error(err)
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
return fi.Size()
|
||||
}
|
||||
|
||||
// IsExist determines whether the file spcified by the given path is exists.
|
||||
func (*myfile) IsExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
// IsBinary determines whether the specified content is a binary file content.
|
||||
func (*myfile) IsBinary(content string) bool {
|
||||
for _, b := range content {
|
||||
if 0 == b {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// IsImg determines whether the specified extension is a image.
|
||||
func (*myfile) IsImg(extension string) bool {
|
||||
ext := strings.ToLower(extension)
|
||||
|
||||
switch ext {
|
||||
case ".jpg", ".jpeg", ".bmp", ".gif", ".png", ".svg", ".ico":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsDir determines whether the specified path is a directory.
|
||||
func (*myfile) IsDir(path string) bool {
|
||||
fio, err := os.Lstat(path)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
|
||||
if nil != err {
|
||||
fileLogger.Warnf("Determines whether [%s] is a directory failed: [%v]", path, err)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return fio.IsDir()
|
||||
}
|
||||
|
||||
// CopyFile copies the source file to the dest file.
|
||||
func (*myfile) CopyFile(source string, dest string) (err error) {
|
||||
sourcefile, err := os.Open(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer sourcefile.Close()
|
||||
|
||||
destfile, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer destfile.Close()
|
||||
|
||||
_, err = io.Copy(destfile, sourcefile)
|
||||
if err == nil {
|
||||
sourceinfo, err := os.Stat(source)
|
||||
if err != nil {
|
||||
err = os.Chmod(dest, sourceinfo.Mode())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDir copies the source directory to the dest directory.
|
||||
func (*myfile) CopyDir(source string, dest string) (err error) {
|
||||
sourceinfo, err := os.Stat(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create dest dir
|
||||
err = os.MkdirAll(dest, sourceinfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
directory, err := os.Open(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer directory.Close()
|
||||
|
||||
objects, err := directory.Readdir(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, obj := range objects {
|
||||
srcFilePath := filepath.Join(source, obj.Name())
|
||||
destFilePath := filepath.Join(dest, obj.Name())
|
||||
|
||||
if obj.IsDir() {
|
||||
// create sub-directories - recursively
|
||||
err = File.CopyDir(srcFilePath, destFilePath)
|
||||
if err != nil {
|
||||
fileLogger.Error(err)
|
||||
}
|
||||
} else {
|
||||
err = File.CopyFile(srcFilePath, destFilePath)
|
||||
if err != nil {
|
||||
fileLogger.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetFileSize(t *testing.T) {
|
||||
size := File.GetFileSize(".")
|
||||
|
||||
t.Log("size of file [.] is [" + strconv.FormatInt(size, 10) + "]")
|
||||
}
|
||||
|
||||
func TestIsExist(t *testing.T) {
|
||||
if !File.IsExist(".") {
|
||||
t.Error(". must exist")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdBinary(t *testing.T) {
|
||||
if File.IsBinary("not binary content") {
|
||||
t.Error("The content should not be binary")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsImg(t *testing.T) {
|
||||
if !File.IsImg(".jpg") {
|
||||
t.Error(".jpg should be a valid extension of a image file")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsDir(t *testing.T) {
|
||||
if !File.IsDir(".") {
|
||||
t.Error(". should be a directory")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyDir(t *testing.T) {
|
||||
dest := filepath.Join(testDir, "util")
|
||||
|
||||
err := File.CopyDir(".", dest)
|
||||
if nil != err {
|
||||
t.Error("Copy dir error: ", err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyFile(t *testing.T) {
|
||||
dest := filepath.Join(testDir, "file.go")
|
||||
|
||||
err := File.CopyFile("./file.go", dest)
|
||||
if nil != err {
|
||||
t.Error("Copy file error: ", err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
118
util/go.go
118
util/go.go
|
@ -1,118 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
pathSeparator = string(os.PathSeparator) // OS-specific path separator
|
||||
pathListSeparator = string(os.PathListSeparator) // OS-specific path list separator
|
||||
)
|
||||
|
||||
type mygo struct{}
|
||||
|
||||
// Go utilities.
|
||||
var Go = mygo{}
|
||||
|
||||
func (*mygo) GetCrossPlatforms() []string {
|
||||
return []string{
|
||||
"darwin_amd64", "linux_amd64", "windows_amd64",
|
||||
"linux_arm", "darwin_386", "linux_386", "windows_386"}
|
||||
}
|
||||
|
||||
// GetAPIPath gets the Go source code path.
|
||||
//
|
||||
// 1. before Go 1.4: $GOROOT/src/pkg
|
||||
// 2. Go 1.4 and after: $GOROOT/src
|
||||
func (*mygo) GetAPIPath() string {
|
||||
ret := runtime.GOROOT() + "/src/pkg" // before Go 1.4
|
||||
if !File.IsExist(ret) {
|
||||
ret = runtime.GOROOT() + "/src" // Go 1.4 and after
|
||||
}
|
||||
|
||||
return filepath.FromSlash(path.Clean(ret))
|
||||
}
|
||||
|
||||
// IsAPI determines whether the specified path belongs to Go API.
|
||||
func (*mygo) IsAPI(path string) bool {
|
||||
apiPath := Go.GetAPIPath()
|
||||
|
||||
return strings.HasPrefix(filepath.FromSlash(path), apiPath)
|
||||
}
|
||||
|
||||
// GetGoFormats gets Go format tools. It may return ["gofmt", "goimports"].
|
||||
func (*mygo) GetGoFormats() []string {
|
||||
ret := []string{"gofmt"}
|
||||
|
||||
p := Go.GetExecutableInGOBIN("goimports")
|
||||
if File.IsExist(p) {
|
||||
ret = append(ret, "goimports")
|
||||
}
|
||||
|
||||
sort.Strings(ret)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetExecutableInGOBIN gets executable file under GOBIN path.
|
||||
//
|
||||
// The specified executable should not with extension, this function will append .exe if on Windows.
|
||||
func (*mygo) GetExecutableInGOBIN(executable string) string {
|
||||
if OS.IsWindows() {
|
||||
executable += ".exe"
|
||||
}
|
||||
|
||||
gopaths := filepath.SplitList(os.Getenv("GOPATH"))
|
||||
|
||||
for _, gopath := range gopaths {
|
||||
// $GOPATH/bin/$GOOS_$GOARCH/executable
|
||||
ret := gopath + pathSeparator + "bin" + pathSeparator +
|
||||
os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + pathSeparator + executable
|
||||
if File.IsExist(ret) {
|
||||
return ret
|
||||
}
|
||||
|
||||
// $GOPATH/bin/{runtime.GOOS}_{runtime.GOARCH}/executable
|
||||
ret = gopath + pathSeparator + "bin" + pathSeparator +
|
||||
runtime.GOOS + "_" + runtime.GOARCH + pathSeparator + executable
|
||||
if File.IsExist(ret) {
|
||||
return ret
|
||||
}
|
||||
|
||||
// $GOPATH/bin/executable
|
||||
ret = gopath + pathSeparator + "bin" + pathSeparator + executable
|
||||
if File.IsExist(ret) {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
// $GOBIN/executable
|
||||
gobin := os.Getenv("GOBIN")
|
||||
if "" != gobin {
|
||||
ret := gobin + pathSeparator + executable
|
||||
if File.IsExist(ret) {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
return "./" + executable
|
||||
}
|
101
util/go_test.go
101
util/go_test.go
|
@ -1,101 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
)
|
||||
|
||||
func TestGetCrossPlatforms(t *testing.T) {
|
||||
crossPlatforms := Go.GetCrossPlatforms()
|
||||
|
||||
if len(crossPlatforms) < 1 {
|
||||
t.Error("should have one platform at least")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAPIPath(t *testing.T) {
|
||||
apiPath := Go.GetAPIPath()
|
||||
|
||||
v := runtime.Version()[2:]
|
||||
|
||||
ver, err := version.NewVersion(v)
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
constraints, err := version.NewConstraint(">= 1.4")
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if constraints.Check(ver) {
|
||||
if !strings.HasSuffix(apiPath, "src") {
|
||||
t.Error("api path should end with \"src\"")
|
||||
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if !strings.HasSuffix(apiPath, "pkg") {
|
||||
t.Error("api path should end with \"pkg\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsAPI(t *testing.T) {
|
||||
apiPath := Go.GetAPIPath()
|
||||
|
||||
if !Go.IsAPI(apiPath) {
|
||||
t.Error("api path root should belong to api path")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
root := "/root"
|
||||
|
||||
if Go.IsAPI(root) {
|
||||
t.Error("root should not belong to api path")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetGoFormats(t *testing.T) {
|
||||
formats := Go.GetGoFormats()
|
||||
|
||||
if len(formats) < 1 {
|
||||
t.Error("should have one go format tool [gofmt] at least")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExecutableInGOBIN(t *testing.T) {
|
||||
bin := Go.GetExecutableInGOBIN("test")
|
||||
|
||||
if OS.IsWindows() {
|
||||
if !strings.HasSuffix(bin, ".exe") {
|
||||
t.Error("Executable binary should end with .exe")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
45
util/net.go
45
util/net.go
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package util includes common utilities.
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
type mynet struct{}
|
||||
|
||||
// Network utilities.
|
||||
var Net = mynet{}
|
||||
|
||||
// LocalIP gets the first NIC's IP address.
|
||||
func (*mynet) LocalIP() (string, error) {
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
|
||||
if nil != err {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, address := range addrs {
|
||||
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||
if nil != ipnet.IP.To4() {
|
||||
return ipnet.IP.String(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("can't get local IP")
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestLocalIP(t *testing.T) {
|
||||
ip, err := Net.LocalIP()
|
||||
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
t.Log(ip)
|
||||
}
|
100
util/os.go
100
util/os.go
|
@ -1,100 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type myos struct{}
|
||||
|
||||
// OS utilities.
|
||||
var OS = myos{}
|
||||
|
||||
// IsWindows determines whether current OS is Windows.
|
||||
func (*myos) IsWindows() bool {
|
||||
return "windows" == runtime.GOOS
|
||||
}
|
||||
|
||||
// Pwd gets the path of current working directory.
|
||||
func (*myos) Pwd() string {
|
||||
file, _ := exec.LookPath(os.Args[0])
|
||||
pwd, _ := filepath.Abs(file)
|
||||
|
||||
return filepath.Dir(pwd)
|
||||
}
|
||||
|
||||
// Home returns the home directory for the executing user.
|
||||
//
|
||||
// This uses an OS-specific method for discovering the home directory.
|
||||
// An error is returned if a home directory cannot be detected.
|
||||
func (*myos) Home() (string, error) {
|
||||
user, err := user.Current()
|
||||
if nil == err {
|
||||
return user.HomeDir, nil
|
||||
}
|
||||
|
||||
// cross compile support
|
||||
|
||||
if OS.IsWindows() {
|
||||
return homeWindows()
|
||||
}
|
||||
|
||||
// Unix-like system, so just assume Unix
|
||||
return homeUnix()
|
||||
}
|
||||
|
||||
func homeUnix() (string, error) {
|
||||
// First prefer the HOME environmental variable
|
||||
if home := os.Getenv("HOME"); home != "" {
|
||||
return home, nil
|
||||
}
|
||||
|
||||
// If that fails, try the shell
|
||||
var stdout bytes.Buffer
|
||||
cmd := exec.Command("sh", "-c", "eval echo ~$USER")
|
||||
cmd.Stdout = &stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result := strings.TrimSpace(stdout.String())
|
||||
if result == "" {
|
||||
return "", errors.New("blank output when reading home directory")
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func homeWindows() (string, error) {
|
||||
drive := os.Getenv("HOMEDRIVE")
|
||||
path := os.Getenv("HOMEPATH")
|
||||
home := drive + path
|
||||
if drive == "" || path == "" {
|
||||
home = os.Getenv("USERPROFILE")
|
||||
}
|
||||
if home == "" {
|
||||
return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
|
||||
}
|
||||
|
||||
return home, nil
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsWiindows(t *testing.T) {
|
||||
goos := runtime.GOOS
|
||||
|
||||
if "windows" == goos && !OS.IsWindows() {
|
||||
t.Error("runtime.GOOS returns [windows]")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestPwd(t *testing.T) {
|
||||
if "" == OS.Pwd() {
|
||||
t.Error("Working directory should not be empty")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestHome(t *testing.T) {
|
||||
home, err := OS.Home()
|
||||
if nil != err {
|
||||
t.Error("Can not get user home")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
t.Log(home)
|
||||
}
|
104
util/panic.go
104
util/panic.go
|
@ -1,104 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/b3log/wide/log"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var logger = log.NewLogger(os.Stdout)
|
||||
|
||||
var (
|
||||
dunno = []byte("???")
|
||||
centerDot = []byte("·")
|
||||
dot = []byte(".")
|
||||
slash = []byte("/")
|
||||
)
|
||||
|
||||
// Recover recovers a panic.
|
||||
func Recover() {
|
||||
if re := recover(); nil != re {
|
||||
stack := stack()
|
||||
logger.Errorf("PANIC RECOVERED: %v\n\t%s\n", re, stack)
|
||||
}
|
||||
}
|
||||
|
||||
// stack implements Stack, skipping 2 frames.
|
||||
func stack() []byte {
|
||||
buf := &bytes.Buffer{} // the returned data
|
||||
// As we loop, we open files and read them. These variables record the currently
|
||||
// loaded file.
|
||||
var lines [][]byte
|
||||
var lastFile string
|
||||
for i := 2; ; i++ { // Caller we care about is the user, 2 frames up
|
||||
pc, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
// Print this much at least. If we can't find the source, it won't show.
|
||||
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
|
||||
if file != lastFile {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
lines = bytes.Split(data, []byte{'\n'})
|
||||
lastFile = file
|
||||
}
|
||||
line-- // in stack trace, lines are 1-indexed but our array is 0-indexed
|
||||
fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// source returns a space-trimmed slice of the n'th line.
|
||||
func source(lines [][]byte, n int) []byte {
|
||||
if n < 0 || n >= len(lines) {
|
||||
return dunno
|
||||
}
|
||||
return bytes.Trim(lines[n], " \t")
|
||||
}
|
||||
|
||||
// function returns, if possible, the name of the function containing the PC.
|
||||
func function(pc uintptr) []byte {
|
||||
fn := runtime.FuncForPC(pc)
|
||||
if fn == nil {
|
||||
return dunno
|
||||
}
|
||||
name := []byte(fn.Name())
|
||||
// The name includes the path name to the package, which is unnecessary
|
||||
// since the file name is already included. Plus, it has center dots.
|
||||
// That is, we see
|
||||
// runtime/debug.*T·ptrmethod
|
||||
// and want
|
||||
// *T.ptrmethod
|
||||
// Since the package path might contains dots (e.g. code.google.com/...),
|
||||
// we first remove the path prefix if there is one.
|
||||
if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
|
||||
name = name[lastslash+1:]
|
||||
}
|
||||
if period := bytes.Index(name, dot); period >= 0 {
|
||||
name = name[period+1:]
|
||||
}
|
||||
name = bytes.Replace(name, centerDot, dot, -1)
|
||||
return name
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRecover(t *testing.T) {
|
||||
defer Recover()
|
||||
|
||||
panic("test panic")
|
||||
}
|
47
util/rand.go
47
util/rand.go
|
@ -1,47 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type myrand struct{}
|
||||
|
||||
// Random utilities.
|
||||
var Rand = myrand{}
|
||||
|
||||
// String returns a random string ['a', 'z'] in the specified length
|
||||
func (*myrand) String(length int) string {
|
||||
bytes := make([]byte, length)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
bytes[i] = byte(Rand.Int('a', 'z'))
|
||||
|
||||
time.Sleep(100 * time.Nanosecond)
|
||||
}
|
||||
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
// Int returns a random integer in range [min, max].
|
||||
func (*myrand) Int(min int, max int) int {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
time.Sleep(100 * time.Nanosecond)
|
||||
|
||||
return min + rand.Intn(max-min)
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
r1 := Rand.String(16)
|
||||
r2 := Rand.String(16)
|
||||
|
||||
if r1 == r2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt(t *testing.T) {
|
||||
r1 := Rand.Int(0, 65535)
|
||||
r2 := Rand.Int(0, 65535)
|
||||
|
||||
if r1 == r2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
115
util/ret.go
115
util/ret.go
|
@ -1,115 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/b3log/wide/log"
|
||||
)
|
||||
|
||||
// Logger.
|
||||
var retLogger = log.NewLogger(os.Stdout)
|
||||
|
||||
// Result.
|
||||
type Result struct {
|
||||
Succ bool `json:"succ"` // successful or not
|
||||
Code int `json:"code"` // return code
|
||||
Msg string `json:"msg"` // message
|
||||
Data interface{} `json:"data"` // data object
|
||||
}
|
||||
|
||||
// NewResult creates a result with Succ=true, Code=0, Msg="", Data=nil.
|
||||
func NewResult() *Result {
|
||||
return &Result{
|
||||
Succ: true,
|
||||
Code: 0,
|
||||
Msg: "",
|
||||
Data: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// RetResult writes HTTP response with "Content-Type, application/json".
|
||||
func RetResult(w http.ResponseWriter, r *http.Request, res *Result) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
data, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
retLogger.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(data)
|
||||
}
|
||||
|
||||
// RetGzResult writes HTTP response with "Content-Type, application/json" and "Content-Encoding, gzip".
|
||||
func RetGzResult(w http.ResponseWriter, r *http.Request, res *Result) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
|
||||
gz := gzip.NewWriter(w)
|
||||
err := json.NewEncoder(gz).Encode(res)
|
||||
if nil != err {
|
||||
retLogger.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = gz.Close()
|
||||
if nil != err {
|
||||
retLogger.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// RetJSON writes HTTP response with "Content-Type, application/json".
|
||||
func RetJSON(w http.ResponseWriter, r *http.Request, res map[string]interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
data, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
retLogger.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(data)
|
||||
}
|
||||
|
||||
// RetGzJSON writes HTTP response with "Content-Type, application/json" and "Content-Encoding, gzip".
|
||||
func RetGzJSON(w http.ResponseWriter, r *http.Request, res map[string]interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
|
||||
gz := gzip.NewWriter(w)
|
||||
err := json.NewEncoder(gz).Encode(res)
|
||||
if nil != err {
|
||||
retLogger.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = gz.Close()
|
||||
if nil != err {
|
||||
retLogger.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
type str struct{}
|
||||
|
||||
// String utilities.
|
||||
var Str = str{}
|
||||
|
||||
// Contains determines whether the str is in the strs.
|
||||
func (*str) Contains(str string, strs []string) bool {
|
||||
for _, v := range strs {
|
||||
if v == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// LCS gets the longest common substring of s1 and s2.
|
||||
//
|
||||
// Refers to http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Longest_common_substring.
|
||||
func (*str) LCS(s1 string, s2 string) string {
|
||||
var m = make([][]int, 1+len(s1))
|
||||
|
||||
for i := 0; i < len(m); i++ {
|
||||
m[i] = make([]int, 1+len(s2))
|
||||
}
|
||||
|
||||
longest := 0
|
||||
xLongest := 0
|
||||
|
||||
for x := 1; x < 1+len(s1); x++ {
|
||||
for y := 1; y < 1+len(s2); y++ {
|
||||
if s1[x-1] == s2[y-1] {
|
||||
m[x][y] = m[x-1][y-1] + 1
|
||||
if m[x][y] > longest {
|
||||
longest = m[x][y]
|
||||
xLongest = x
|
||||
}
|
||||
} else {
|
||||
m[x][y] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s1[xLongest-longest : xLongest]
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
if !Str.Contains("123", []string{"123", "345"}) {
|
||||
t.Error("[\"123\", \"345\"] should contain \"123\"")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestLCS(t *testing.T) {
|
||||
str := Str.LCS("123456", "abc34def")
|
||||
|
||||
if "34" != str {
|
||||
t.Error("[\"123456\"] and [\"abc34def\"] should have the longest common substring [\"34\"]")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
230
util/zip.go
230
util/zip.go
|
@ -1,230 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
type myzip struct{}
|
||||
|
||||
// Zip utilities.
|
||||
var Zip = myzip{}
|
||||
|
||||
// ZipFile represents a zip file.
|
||||
type ZipFile struct {
|
||||
zipFile *os.File
|
||||
writer *zip.Writer
|
||||
}
|
||||
|
||||
// Create creates a zip file with the specified filename.
|
||||
func (*myzip) Create(filename string) (*ZipFile, error) {
|
||||
file, err := os.Create(filename)
|
||||
if nil != err {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ZipFile{zipFile: file, writer: zip.NewWriter(file)}, nil
|
||||
}
|
||||
|
||||
// Close closes the zip file writer.
|
||||
func (z *ZipFile) Close() error {
|
||||
err := z.writer.Close()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
return z.zipFile.Close() // close the underlying writer
|
||||
}
|
||||
|
||||
// AddEntryN adds entries.
|
||||
func (z *ZipFile) AddEntryN(path string, names ...string) error {
|
||||
for _, name := range names {
|
||||
zipPath := filepath.Join(path, name)
|
||||
err := z.AddEntry(zipPath, name)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddEntry adds a entry.
|
||||
func (z *ZipFile) AddEntry(path, name string) error {
|
||||
fi, err := os.Stat(name)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
fh, err := zip.FileInfoHeader(fi)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
fh.Name = filepath.ToSlash(filepath.Clean(path))
|
||||
fh.Method = zip.Deflate // data compression algorithm
|
||||
|
||||
if fi.IsDir() {
|
||||
fh.Name = fh.Name + "/" // be care the ending separator
|
||||
}
|
||||
|
||||
entry, err := z.writer.CreateHeader(fh)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
file, err := os.Open(name)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(entry, file)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// AddDirectoryN adds directories.
|
||||
func (z *ZipFile) AddDirectoryN(path string, names ...string) error {
|
||||
for _, name := range names {
|
||||
err := z.AddDirectory(path, name)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddDirectory adds a directory.
|
||||
func (z *ZipFile) AddDirectory(path, dirName string) error {
|
||||
files, err := ioutil.ReadDir(dirName)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
if 0 == len(files) {
|
||||
err := z.AddEntry(path, dirName)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
localPath := filepath.Join(dirName, file.Name())
|
||||
zipPath := filepath.Join(path, file.Name())
|
||||
|
||||
err = nil
|
||||
if file.IsDir() {
|
||||
err = z.AddDirectory(zipPath, localPath)
|
||||
} else {
|
||||
err = z.AddEntry(zipPath, localPath)
|
||||
}
|
||||
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func cloneZipItem(f *zip.File, dest string) error {
|
||||
// create full directory path
|
||||
fileName := f.Name
|
||||
|
||||
if !utf8.ValidString(fileName) {
|
||||
data, err := ioutil.ReadAll(transform.NewReader(bytes.NewReader([]byte(fileName)), simplifiedchinese.GB18030.NewDecoder()))
|
||||
if nil == err {
|
||||
fileName = string(data)
|
||||
} else {
|
||||
logger.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
path := filepath.Join(dest, fileName)
|
||||
|
||||
err := os.MkdirAll(filepath.Dir(path), os.ModeDir|os.ModePerm)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.FileInfo().IsDir() {
|
||||
err = os.Mkdir(path, os.ModeDir|os.ModePerm)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// clone if item is a file
|
||||
|
||||
rc, err := f.Open()
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
defer rc.Close()
|
||||
|
||||
// use os.Create() since Zip don't store file permissions
|
||||
fileCopy, err := os.Create(path)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
defer fileCopy.Close()
|
||||
|
||||
_, err = io.Copy(fileCopy, rc)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unzip extracts a zip file specified by the zipFilePath to the destination.
|
||||
func (*myzip) Unzip(zipFilePath, destination string) error {
|
||||
r, err := zip.OpenReader(zipFilePath)
|
||||
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
|
||||
defer r.Close()
|
||||
|
||||
for _, f := range r.File {
|
||||
err = cloneZipItem(f, destination)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
149
util/zip_test.go
149
util/zip_test.go
|
@ -1,149 +0,0 @@
|
|||
// Copyright (c) 2014-present, b3log.org
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var testDir = "../tmp"
|
||||
var packageName = filepath.Join(testDir, "test_zip")
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
zipFile, err := Zip.Create(packageName + ".zip")
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
zipFile.AddDirectoryN(".", ".")
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = zipFile.Close()
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnzip(t *testing.T) {
|
||||
err := Zip.Unzip(packageName+".zip", packageName)
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func _TestEmptyDir(t *testing.T) {
|
||||
dir1 := "/dir/subDir1"
|
||||
dir2 := "/dir/subDir2"
|
||||
|
||||
err := os.MkdirAll(packageName+dir1, os.ModeDir)
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = os.MkdirAll(packageName+dir2, os.ModeDir)
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.Create(packageName + dir2 + "/file")
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
f.Close()
|
||||
|
||||
zipFile, err := Zip.Create(packageName + "/dir.zip")
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
zipFile.AddDirectoryN("dir", packageName+"/dir")
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = zipFile.Close()
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = Zip.Unzip(packageName+"/dir.zip", packageName+"/unzipDir")
|
||||
if nil != err {
|
||||
t.Error(err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !File.IsExist(packageName+"/unzipDir") || !File.IsDir(packageName+"/unzipDir") {
|
||||
t.Error("Unzip failed")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !File.IsExist(packageName+"/unzipDir"+dir1) || !File.IsDir(packageName+"/unzipDir"+dir1) {
|
||||
t.Error("Unzip failed")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !File.IsExist(packageName+"/unzipDir"+dir2) || !File.IsDir(packageName+"/unzipDir"+dir2) {
|
||||
t.Error("Unzip failed")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !File.IsExist(packageName+"/unzipDir"+dir2+"/file") || File.IsDir(packageName+"/unzipDir"+dir2+"/file") {
|
||||
t.Error("Unzip failed")
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
logger.Info(testDir)
|
||||
|
||||
retCode := m.Run()
|
||||
|
||||
// clean test data
|
||||
os.RemoveAll(testDir + "/test_zip")
|
||||
os.RemoveAll(testDir + "/util")
|
||||
os.RemoveAll(testDir + "/file.go")
|
||||
os.RemoveAll(testDir + "/test_zip.zip")
|
||||
|
||||
os.Exit(retCode)
|
||||
}
|
Loading…
Reference in New Issue