tech: upgraded macaron & macaron inject, binding, session
This commit is contained in:
Generated
-24
@@ -1,24 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
.idea
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.iml
|
||||
+4
-8
@@ -1,7 +1,7 @@
|
||||
Common functions
|
||||
===
|
||||
Common Functions
|
||||
================
|
||||
|
||||
[](https://drone.io/github.com/Unknwon/com/latest) [](http://gowalker.org/github.com/Unknwon/com)
|
||||
[](https://travis-ci.org/Unknwon/com) [](http://gowalker.org/github.com/Unknwon/com)
|
||||
|
||||
This is an open source project for commonly used functions for the Go programming language.
|
||||
|
||||
@@ -17,8 +17,4 @@ Your contribute is welcome, but you have to check following steps after you adde
|
||||
2. Make sure you wrote test cases with any possible condition for **all functions** in file `*_test.go`.
|
||||
3. Make sure you wrote benchmarks for **all functions** in file `*_test.go`.
|
||||
4. Make sure you wrote useful examples for **all functions** in file `example_test.go`.
|
||||
5. Make sure you ran `go test -bench="."` and got **PASS** .
|
||||
|
||||
## Performance
|
||||
|
||||
See results on [drone.io](https://drone.io/github.com/Unknwon/com/latest) by `go test -bench="."`.
|
||||
5. Make sure you ran `go test` and got **PASS** .
|
||||
|
||||
-140
@@ -1,140 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestColorLogS(t *testing.T) {
|
||||
if runtime.GOOS != "windows" {
|
||||
// Trace + path.
|
||||
cls := ColorLogS("[TRAC] Trace level test with path( %s )", "/path/to/somethere")
|
||||
clsR := fmt.Sprintf(
|
||||
"[\033[%dmTRAC%s] Trace level test with path(\033[%dm%s%s)",
|
||||
Blue, EndColor, Yellow, "/path/to/somethere", EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Error + error.
|
||||
cls = ColorLogS("[ERRO] Error level test with error[ %s ]", "test error")
|
||||
clsR = fmt.Sprintf(
|
||||
"[\033[%dmERRO%s] Error level test with error[\033[%dm%s%s]",
|
||||
Red, EndColor, Red, "test error", EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Warning + highlight.
|
||||
cls = ColorLogS("[WARN] Warnning level test with highlight # %s #", "special offer!")
|
||||
clsR = fmt.Sprintf(
|
||||
"[\033[%dmWARN%s] Warnning level test with highlight \033[%dm%s%s",
|
||||
Magenta, EndColor, Gray, "special offer!", EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Success.
|
||||
cls = ColorLogS("[SUCC] Success level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[\033[%dmSUCC%s] Success level test",
|
||||
Green, EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Default.
|
||||
cls = ColorLogS("[INFO] Default level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[INFO] Default level test")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
} else {
|
||||
// Trace + path.
|
||||
cls := ColorLogS("[TRAC] Trace level test with path( %s )", "/path/to/somethere")
|
||||
clsR := fmt.Sprintf(
|
||||
"[TRAC] Trace level test with path(%s)",
|
||||
"/path/to/somethere")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Error + error.
|
||||
cls = ColorLogS("[ERRO] Error level test with error[ %s ]", "test error")
|
||||
clsR = fmt.Sprintf(
|
||||
"[ERRO] Error level test with error[%s]",
|
||||
"test error")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Warning + highlight.
|
||||
cls = ColorLogS("[WARN] Warnning level test with highlight # %s #", "special offer!")
|
||||
clsR = fmt.Sprintf(
|
||||
"[WARN] Warnning level test with highlight %s",
|
||||
"special offer!")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Success.
|
||||
cls = ColorLogS("[SUCC] Success level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[SUCC] Success level test")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Default.
|
||||
cls = ColorLogS("[INFO] Default level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[INFO] Default level test")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecCmd(t *testing.T) {
|
||||
stdout, stderr, err := ExecCmd("go", "help", "get")
|
||||
if err != nil {
|
||||
t.Errorf("ExecCmd:\n Expect => %v\n Got => %v\n", nil, err)
|
||||
} else if len(stderr) != 0 {
|
||||
t.Errorf("ExecCmd:\n Expect => %s\n Got => %s\n", "", stderr)
|
||||
} else if !strings.HasPrefix(stdout, "usage: go get") {
|
||||
t.Errorf("ExecCmd:\n Expect => %s\n Got => %s\n", "usage: go get", stdout)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkColorLogS(b *testing.B) {
|
||||
log := fmt.Sprintf(
|
||||
"[WARN] This is a tesing log that should be colored, path( %s ),"+
|
||||
" highlight # %s #, error [ %s ].",
|
||||
"path to somewhere", "highlighted content", "tesing error")
|
||||
for i := 0; i < b.N; i++ {
|
||||
ColorLogS(log)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExecCmd(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ExecCmd("go", "help", "get")
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -32,7 +32,7 @@ func (f StrTo) Uint8() (uint8, error) {
|
||||
}
|
||||
|
||||
func (f StrTo) Int() (int, error) {
|
||||
v, err := strconv.ParseInt(f.String(), 10, 32)
|
||||
v, err := strconv.ParseInt(f.String(), 10, 0)
|
||||
return int(v), err
|
||||
}
|
||||
|
||||
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
// Copyright 2014 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestHexStr2int(t *testing.T) {
|
||||
Convey("Convert hex format string to decimal", t, func() {
|
||||
hexDecs := map[string]int{
|
||||
"1": 1,
|
||||
"002": 2,
|
||||
"011": 17,
|
||||
"0a1": 161,
|
||||
"35e": 862,
|
||||
}
|
||||
|
||||
for hex, dec := range hexDecs {
|
||||
val, err := HexStr2int(hex)
|
||||
So(err, ShouldBeNil)
|
||||
So(val, ShouldEqual, dec)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestInt2HexStr(t *testing.T) {
|
||||
Convey("Convert decimal to hex format string", t, func() {
|
||||
decHexs := map[int]string{
|
||||
1: "1",
|
||||
2: "2",
|
||||
17: "11",
|
||||
161: "a1",
|
||||
862: "35e",
|
||||
}
|
||||
|
||||
for dec, hex := range decHexs {
|
||||
val := Int2HexStr(dec)
|
||||
So(val, ShouldEqual, hex)
|
||||
}
|
||||
})
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestIsDir(t *testing.T) {
|
||||
Convey("Check if given path is a directory", t, func() {
|
||||
Convey("Pass a file name", func() {
|
||||
So(IsDir("file.go"), ShouldEqual, false)
|
||||
})
|
||||
Convey("Pass a directory name", func() {
|
||||
So(IsDir("testdata"), ShouldEqual, true)
|
||||
})
|
||||
Convey("Pass a invalid path", func() {
|
||||
So(IsDir("foo"), ShouldEqual, false)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestCopyDir(t *testing.T) {
|
||||
Convey("Items of two slices should be same", t, func() {
|
||||
s1, err := StatDir("testdata", true)
|
||||
So(err, ShouldEqual, nil)
|
||||
|
||||
err = CopyDir("testdata", "testdata2")
|
||||
So(err, ShouldEqual, nil)
|
||||
|
||||
s2, err := StatDir("testdata2", true)
|
||||
os.RemoveAll("testdata2")
|
||||
So(err, ShouldEqual, nil)
|
||||
|
||||
So(CompareSliceStr(s1, s2), ShouldEqual, true)
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkIsDir(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsDir("file.go")
|
||||
}
|
||||
}
|
||||
-299
@@ -1,299 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
// ------------------------------
|
||||
// cmd.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleColorLogS() {
|
||||
coloredLog := com.ColorLogS(fmt.Sprintf(
|
||||
"[WARN] This is a tesing log that should be colored, path( %s ),"+
|
||||
" highlight # %s #, error [ %s ].",
|
||||
"path to somewhere", "highlighted content", "tesing error"))
|
||||
fmt.Println(coloredLog)
|
||||
}
|
||||
|
||||
func ExampleColorLog() {
|
||||
com.ColorLog(fmt.Sprintf(
|
||||
"[WARN] This is a tesing log that should be colored, path( %s ),"+
|
||||
" highlight # %s #, error [ %s ].",
|
||||
"path to somewhere", "highlighted content", "tesing error"))
|
||||
}
|
||||
|
||||
func ExampleExecCmd() {
|
||||
stdout, stderr, err := com.ExecCmd("go", "help", "get")
|
||||
fmt.Println(stdout, stderr, err)
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// html.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleHtml2JS() {
|
||||
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
|
||||
js := string(com.Html2JS([]byte(htm)))
|
||||
fmt.Println(js)
|
||||
// Output: <div id=\"button\" class=\"btn\">Click me</div>\n
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// path.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleGetGOPATHs() {
|
||||
gps := com.GetGOPATHs()
|
||||
fmt.Println(gps)
|
||||
}
|
||||
|
||||
func ExampleGetSrcPath() {
|
||||
srcPath, err := com.GetSrcPath("github.com/Unknwon/com")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(srcPath)
|
||||
}
|
||||
|
||||
func ExampleHomeDir() {
|
||||
hd, err := com.HomeDir()
|
||||
fmt.Println(hd, err)
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// file.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsFile() {
|
||||
if com.IsFile("file.go") {
|
||||
fmt.Println("file.go exists")
|
||||
return
|
||||
}
|
||||
fmt.Println("file.go is not a file or does not exist")
|
||||
}
|
||||
|
||||
func ExampleIsExist() {
|
||||
if com.IsExist("file.go") {
|
||||
fmt.Println("file.go exists")
|
||||
return
|
||||
}
|
||||
fmt.Println("file.go does not exist")
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// dir.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsDir() {
|
||||
if com.IsDir("files") {
|
||||
fmt.Println("directory 'files' exists")
|
||||
return
|
||||
}
|
||||
fmt.Println("'files' is not a directory or does not exist")
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// string.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsLetter() {
|
||||
fmt.Println(com.IsLetter('1'))
|
||||
fmt.Println(com.IsLetter('['))
|
||||
fmt.Println(com.IsLetter('a'))
|
||||
fmt.Println(com.IsLetter('Z'))
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleExpand() {
|
||||
match := map[string]string{
|
||||
"domain": "gowalker.org",
|
||||
"subdomain": "github.com",
|
||||
}
|
||||
s := "http://{domain}/{subdomain}/{0}/{1}"
|
||||
fmt.Println(com.Expand(s, match, "Unknwon", "gowalker"))
|
||||
// Output: http://gowalker.org/github.com/Unknwon/gowalker
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// http.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleHttpGet() ([]byte, error) {
|
||||
rc, err := com.HttpGet(&http.Client{}, "http://gowalker.org", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p, err := ioutil.ReadAll(rc)
|
||||
rc.Close()
|
||||
return p, err
|
||||
}
|
||||
|
||||
func ExampleHttpGetBytes() ([]byte, error) {
|
||||
p, err := com.HttpGetBytes(&http.Client{}, "http://gowalker.org", nil)
|
||||
return p, err
|
||||
}
|
||||
|
||||
func ExampleHttpGetJSON() interface{} {
|
||||
j := com.HttpGetJSON(&http.Client{}, "http://gowalker.org", nil)
|
||||
return j
|
||||
}
|
||||
|
||||
type rawFile struct {
|
||||
name string
|
||||
rawURL string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (rf *rawFile) Name() string {
|
||||
return rf.name
|
||||
}
|
||||
|
||||
func (rf *rawFile) RawUrl() string {
|
||||
return rf.rawURL
|
||||
}
|
||||
|
||||
func (rf *rawFile) Data() []byte {
|
||||
return rf.data
|
||||
}
|
||||
|
||||
func (rf *rawFile) SetData(p []byte) {
|
||||
rf.data = p
|
||||
}
|
||||
|
||||
func ExampleFetchFiles() {
|
||||
// Code that should be outside of your function body.
|
||||
// type rawFile struct {
|
||||
// name string
|
||||
// rawURL string
|
||||
// data []byte
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Name() string {
|
||||
// return rf.name
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) RawUrl() string {
|
||||
// return rf.rawURL
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Data() []byte {
|
||||
// return rf.data
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) SetData(p []byte) {
|
||||
// rf.data = p
|
||||
// }
|
||||
|
||||
files := []com.RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com/foo"},
|
||||
}
|
||||
err := com.FetchFiles(&http.Client{}, files, nil)
|
||||
fmt.Println(err, len(files[0].Data()), len(files[1].Data()))
|
||||
}
|
||||
|
||||
func ExampleFetchFilesCurl() {
|
||||
// Code that should be outside of your function body.
|
||||
// type rawFile struct {
|
||||
// name string
|
||||
// rawURL string
|
||||
// data []byte
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Name() string {
|
||||
// return rf.name
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) RawUrl() string {
|
||||
// return rf.rawURL
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Data() []byte {
|
||||
// return rf.data
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) SetData(p []byte) {
|
||||
// rf.data = p
|
||||
// }
|
||||
|
||||
files := []com.RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com/foo"},
|
||||
}
|
||||
err := com.FetchFilesCurl(files)
|
||||
fmt.Println(err, len(files[0].Data()), len(files[1].Data()))
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// regex.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsEmail() {
|
||||
fmt.Println(com.IsEmail("test@example.com"))
|
||||
fmt.Println(com.IsEmail("@example.com"))
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleIsUrl() {
|
||||
fmt.Println(com.IsUrl("http://example.com"))
|
||||
fmt.Println(com.IsUrl("http//example.com"))
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// slice.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleAppendStr() {
|
||||
s := []string{"a"}
|
||||
s = com.AppendStr(s, "a")
|
||||
s = com.AppendStr(s, "b")
|
||||
fmt.Println(s)
|
||||
// Output: [a b]
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestIsFile(t *testing.T) {
|
||||
if !IsFile("file.go") {
|
||||
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", true, false)
|
||||
}
|
||||
|
||||
if IsFile("testdata") {
|
||||
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
|
||||
if IsFile("files.go") {
|
||||
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsExist(t *testing.T) {
|
||||
Convey("Check if file or directory exists", t, func() {
|
||||
Convey("Pass a file name that exists", func() {
|
||||
So(IsExist("file.go"), ShouldEqual, true)
|
||||
})
|
||||
Convey("Pass a directory name that exists", func() {
|
||||
So(IsExist("testdata"), ShouldEqual, true)
|
||||
})
|
||||
Convey("Pass a directory name that does not exist", func() {
|
||||
So(IsExist(".hg"), ShouldEqual, false)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkIsFile(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsFile("file.go")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsExist(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsExist("file.go")
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHtml2JS(t *testing.T) {
|
||||
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
|
||||
js := string(Html2JS([]byte(htm)))
|
||||
jsR := `<div id=\"button\" class=\"btn\">Click me</div>\n`
|
||||
if js != jsR {
|
||||
t.Errorf("Html2JS:\n Expect => %s\n Got => %s\n", jsR, js)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHtml2JS(b *testing.B) {
|
||||
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
|
||||
for i := 0; i < b.N; i++ {
|
||||
Html2JS([]byte(htm))
|
||||
}
|
||||
}
|
||||
-111
@@ -1,111 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var examplePrefix = `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Example Domain</title>
|
||||
`
|
||||
|
||||
func TestHttpGet(t *testing.T) {
|
||||
// 200.
|
||||
rc, err := HttpGet(&http.Client{}, "http://example.com", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("HttpGet:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
p, err := ioutil.ReadAll(rc)
|
||||
if err != nil {
|
||||
t.Errorf("HttpGet:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
s := string(p)
|
||||
if !strings.HasPrefix(s, examplePrefix) {
|
||||
t.Errorf("HttpGet:\n Expect => %s\n Got => %s\n", examplePrefix, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHttpGetBytes(t *testing.T) {
|
||||
p, err := HttpGetBytes(&http.Client{}, "http://example.com", nil)
|
||||
if err != nil {
|
||||
t.Errorf("HttpGetBytes:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
s := string(p)
|
||||
if !strings.HasPrefix(s, examplePrefix) {
|
||||
t.Errorf("HttpGet:\n Expect => %s\n Got => %s\n", examplePrefix, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHttpGetJSON(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
type rawFile struct {
|
||||
name string
|
||||
rawURL string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (rf *rawFile) Name() string {
|
||||
return rf.name
|
||||
}
|
||||
|
||||
func (rf *rawFile) RawUrl() string {
|
||||
return rf.rawURL
|
||||
}
|
||||
|
||||
func (rf *rawFile) Data() []byte {
|
||||
return rf.data
|
||||
}
|
||||
|
||||
func (rf *rawFile) SetData(p []byte) {
|
||||
rf.data = p
|
||||
}
|
||||
|
||||
func TestFetchFiles(t *testing.T) {
|
||||
files := []RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
}
|
||||
err := FetchFiles(&http.Client{}, files, nil)
|
||||
if err != nil {
|
||||
t.Errorf("FetchFiles:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
} else if len(files[0].Data()) != 1270 {
|
||||
t.Errorf("FetchFiles:\n Expect => %d\n Got => %d\n", 1270, len(files[0].Data()))
|
||||
} else if len(files[1].Data()) != 1270 {
|
||||
t.Errorf("FetchFiles:\n Expect => %d\n Got => %d\n", 1270, len(files[1].Data()))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchFilesCurl(t *testing.T) {
|
||||
files := []RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
}
|
||||
err := FetchFilesCurl(files)
|
||||
if err != nil {
|
||||
t.Errorf("FetchFilesCurl:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
} else if len(files[0].Data()) != 1270 {
|
||||
t.Errorf("FetchFilesCurl:\n Expect => %d\n Got => %d\n", 1270, len(files[0].Data()))
|
||||
} else if len(files[1].Data()) != 1270 {
|
||||
t.Errorf("FetchFilesCurl:\n Expect => %d\n Got => %d\n", 1270, len(files[1].Data()))
|
||||
}
|
||||
}
|
||||
+10
-5
@@ -14,11 +14,16 @@
|
||||
|
||||
package com
|
||||
|
||||
// PowInt is int type of math.Pow function.
|
||||
// PowInt is int type of math.Pow function.
|
||||
func PowInt(x int, y int) int {
|
||||
num := 1
|
||||
for i := 0; i < y; i++ {
|
||||
num *= x
|
||||
if y <= 0 {
|
||||
return 1
|
||||
} else {
|
||||
if y % 2 == 0 {
|
||||
sqrt := PowInt(x, y/2)
|
||||
return sqrt * sqrt
|
||||
} else {
|
||||
return PowInt(x, y-1) * x
|
||||
}
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
+3
-3
@@ -64,9 +64,9 @@ func GetSrcPath(importPath string) (appPath string, err error) {
|
||||
// it returns error when the variable does not exist.
|
||||
func HomeDir() (home string, err error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
|
||||
if home == "" {
|
||||
home = os.Getenv("USERPROFILE")
|
||||
home = os.Getenv("USERPROFILE")
|
||||
if len(home) == 0 {
|
||||
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
|
||||
}
|
||||
} else {
|
||||
home = os.Getenv("HOME")
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetGOPATHs(t *testing.T) {
|
||||
var gpsR []string
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
gpsR = []string{"path/to/gopath1", "path/to/gopath2", "path/to/gopath3"}
|
||||
os.Setenv("GOPATH", "path/to/gopath1:path/to/gopath2:path/to/gopath3")
|
||||
} else {
|
||||
gpsR = []string{"path/to/gopath1", "path/to/gopath2", "path/to/gopath3"}
|
||||
os.Setenv("GOPATH", "path\\to\\gopath1;path\\to\\gopath2;path\\to\\gopath3")
|
||||
}
|
||||
|
||||
gps := GetGOPATHs()
|
||||
if !CompareSliceStr(gps, gpsR) {
|
||||
t.Errorf("GetGOPATHs:\n Expect => %s\n Got => %s\n", gpsR, gps)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSrcPath(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestHomeDir(t *testing.T) {
|
||||
_, err := HomeDir()
|
||||
if err != nil {
|
||||
t.Errorf("HomeDir:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetGOPATHs(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
GetGOPATHs()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetSrcPath(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
GetSrcPath("github.com/Unknwon/com")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHomeDir(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
HomeDir()
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsEmail(t *testing.T) {
|
||||
emails := map[string]bool{
|
||||
`test@example.com`: true,
|
||||
`single-character@b.org`: true,
|
||||
`uncommon_address@test.museum`: true,
|
||||
`local@sld.UPPER`: true,
|
||||
`@missing.org`: false,
|
||||
`missing@.com`: false,
|
||||
`missing@qq.`: false,
|
||||
`wrong-ip@127.1.1.1.26`: false,
|
||||
}
|
||||
for e, r := range emails {
|
||||
b := IsEmail(e)
|
||||
if b != r {
|
||||
t.Errorf("IsEmail:\n Expect => %v\n Got => %v\n", r, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsUrl(t *testing.T) {
|
||||
urls := map[string]bool{
|
||||
"http://www.example.com": true,
|
||||
"http://example.com": true,
|
||||
"http://example.com?user=test&password=test": true,
|
||||
"http://example.com?user=test#login": true,
|
||||
"ftp://example.com": true,
|
||||
"https://example.com": true,
|
||||
"htp://example.com": false,
|
||||
"http//example.com": false,
|
||||
"http://example": true,
|
||||
}
|
||||
for u, r := range urls {
|
||||
b := IsUrl(u)
|
||||
if b != r {
|
||||
t.Errorf("IsUrl:\n Expect => %v\n Got => %v\n", r, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsEmail(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsEmail("test@example.com")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsUrl(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsEmail("http://example.com")
|
||||
}
|
||||
}
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAppendStr(t *testing.T) {
|
||||
Convey("Append a string to a slice with no duplicates", t, func() {
|
||||
s := []string{"a"}
|
||||
|
||||
Convey("Append a string that does not exist in slice", func() {
|
||||
s = AppendStr(s, "b")
|
||||
So(len(s), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("Append a string that does exist in slice", func() {
|
||||
s = AppendStr(s, "b")
|
||||
So(len(s), ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestCompareSliceStr(t *testing.T) {
|
||||
Convey("Compares two 'string' type slices with elements and order", t, func() {
|
||||
Convey("Compare two slices that do have same elements and order", func() {
|
||||
So(CompareSliceStr(
|
||||
[]string{"1", "2", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that do have same elements but does not have same order", func() {
|
||||
So(!CompareSliceStr(
|
||||
[]string{"2", "1", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that have different number of elements", func() {
|
||||
So(!CompareSliceStr(
|
||||
[]string{"2", "1"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestCompareSliceStrU(t *testing.T) {
|
||||
Convey("Compare two 'string' type slices with elements and ignore the order", t, func() {
|
||||
Convey("Compare two slices that do have same elements and order", func() {
|
||||
So(CompareSliceStrU(
|
||||
[]string{"1", "2", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that do have same elements but does not have same order", func() {
|
||||
So(CompareSliceStrU(
|
||||
[]string{"2", "1", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that have different number of elements", func() {
|
||||
So(!CompareSliceStrU(
|
||||
[]string{"2", "1"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkAppendStr(b *testing.B) {
|
||||
s := []string{"a"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
s = AppendStr(s, fmt.Sprint(b.N%3))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompareSliceStr(b *testing.B) {
|
||||
s1 := []string{"1", "2", "3"}
|
||||
s2 := []string{"1", "2", "3"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
CompareSliceStr(s1, s2)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompareSliceStrU(b *testing.B) {
|
||||
s1 := []string{"1", "4", "2", "3"}
|
||||
s2 := []string{"1", "2", "3", "4"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
CompareSliceStrU(s1, s2)
|
||||
}
|
||||
}
|
||||
+135
-22
@@ -15,53 +15,66 @@
|
||||
package com
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
r "math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// AESEncrypt encrypts text and given key with AES.
|
||||
func AESEncrypt(key, text []byte) ([]byte, error) {
|
||||
// AESGCMEncrypt encrypts plaintext with the given key using AES in GCM mode.
|
||||
func AESGCMEncrypt(key, plaintext []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := base64.StdEncoding.EncodeToString(text)
|
||||
ciphertext := make([]byte, aes.BlockSize+len(b))
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfb := cipher.NewCFBEncrypter(block, iv)
|
||||
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
|
||||
return ciphertext, nil
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
if _, err := rand.Read(nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ciphertext := gcm.Seal(nil, nonce, plaintext, nil)
|
||||
return append(nonce, ciphertext...), nil
|
||||
}
|
||||
|
||||
// AESDecrypt decrypts text and given key with AES.
|
||||
func AESDecrypt(key, text []byte) ([]byte, error) {
|
||||
// AESGCMDecrypt decrypts ciphertext with the given key using AES in GCM mode.
|
||||
func AESGCMDecrypt(key, ciphertext []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(text) < aes.BlockSize {
|
||||
return nil, errors.New("ciphertext too short")
|
||||
}
|
||||
iv := text[:aes.BlockSize]
|
||||
text = text[aes.BlockSize:]
|
||||
cfb := cipher.NewCFBDecrypter(block, iv)
|
||||
cfb.XORKeyStream(text, text)
|
||||
data, err := base64.StdEncoding.DecodeString(string(text))
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
|
||||
size := gcm.NonceSize()
|
||||
if len(ciphertext)-size <= 0 {
|
||||
return nil, errors.New("Ciphertext is empty")
|
||||
}
|
||||
|
||||
nonce := ciphertext[:size]
|
||||
ciphertext = ciphertext[size:]
|
||||
|
||||
plainText, err := gcm.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plainText, nil
|
||||
}
|
||||
|
||||
// IsLetter returns true if the 'l' is an English letter.
|
||||
@@ -138,3 +151,103 @@ func RandomCreateBytes(n int, alphabets ...byte) []byte {
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
// ToSnakeCase can convert all upper case characters in a string to
|
||||
// underscore format.
|
||||
//
|
||||
// Some samples.
|
||||
// "FirstName" => "first_name"
|
||||
// "HTTPServer" => "http_server"
|
||||
// "NoHTTPS" => "no_https"
|
||||
// "GO_PATH" => "go_path"
|
||||
// "GO PATH" => "go_path" // space is converted to underscore.
|
||||
// "GO-PATH" => "go_path" // hyphen is converted to underscore.
|
||||
//
|
||||
// From https://github.com/huandu/xstrings
|
||||
func ToSnakeCase(str string) string {
|
||||
if len(str) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
var prev, r0, r1 rune
|
||||
var size int
|
||||
|
||||
r0 = '_'
|
||||
|
||||
for len(str) > 0 {
|
||||
prev = r0
|
||||
r0, size = utf8.DecodeRuneInString(str)
|
||||
str = str[size:]
|
||||
|
||||
switch {
|
||||
case r0 == utf8.RuneError:
|
||||
buf.WriteByte(byte(str[0]))
|
||||
|
||||
case unicode.IsUpper(r0):
|
||||
if prev != '_' {
|
||||
buf.WriteRune('_')
|
||||
}
|
||||
|
||||
buf.WriteRune(unicode.ToLower(r0))
|
||||
|
||||
if len(str) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
r0, size = utf8.DecodeRuneInString(str)
|
||||
str = str[size:]
|
||||
|
||||
if !unicode.IsUpper(r0) {
|
||||
buf.WriteRune(r0)
|
||||
break
|
||||
}
|
||||
|
||||
// find next non-upper-case character and insert `_` properly.
|
||||
// it's designed to convert `HTTPServer` to `http_server`.
|
||||
// if there are more than 2 adjacent upper case characters in a word,
|
||||
// treat them as an abbreviation plus a normal word.
|
||||
for len(str) > 0 {
|
||||
r1 = r0
|
||||
r0, size = utf8.DecodeRuneInString(str)
|
||||
str = str[size:]
|
||||
|
||||
if r0 == utf8.RuneError {
|
||||
buf.WriteRune(unicode.ToLower(r1))
|
||||
buf.WriteByte(byte(str[0]))
|
||||
break
|
||||
}
|
||||
|
||||
if !unicode.IsUpper(r0) {
|
||||
if r0 == '_' || r0 == ' ' || r0 == '-' {
|
||||
r0 = '_'
|
||||
|
||||
buf.WriteRune(unicode.ToLower(r1))
|
||||
} else {
|
||||
buf.WriteRune('_')
|
||||
buf.WriteRune(unicode.ToLower(r1))
|
||||
buf.WriteRune(r0)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
buf.WriteRune(unicode.ToLower(r1))
|
||||
}
|
||||
|
||||
if len(str) == 0 || r0 == '_' {
|
||||
buf.WriteRune(unicode.ToLower(r0))
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
if r0 == ' ' || r0 == '-' {
|
||||
r0 = '_'
|
||||
}
|
||||
|
||||
buf.WriteRune(r0)
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// http://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 com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsLetter(t *testing.T) {
|
||||
if IsLetter('1') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
|
||||
if IsLetter('[') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
|
||||
if !IsLetter('a') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", true, false)
|
||||
}
|
||||
|
||||
if !IsLetter('Z') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", true, false)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpand(t *testing.T) {
|
||||
match := map[string]string{
|
||||
"domain": "gowalker.org",
|
||||
"subdomain": "github.com",
|
||||
}
|
||||
s := "http://{domain}/{subdomain}/{0}/{1}"
|
||||
sR := "http://gowalker.org/github.com/Unknwon/gowalker"
|
||||
if Expand(s, match, "Unknwon", "gowalker") != sR {
|
||||
t.Errorf("Expand:\n Expect => %s\n Got => %s\n", sR, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
if Reverse("abcdefg") != "gfedcba" {
|
||||
t.Errorf("Reverse:\n Except => %s\n Got =>%s\n", "gfedcba", Reverse("abcdefg"))
|
||||
}
|
||||
if Reverse("上善若水厚德载物") != "物载德厚水若善上" {
|
||||
t.Errorf("Reverse:\n Except => %s\n Got =>%s\n", "物载德厚水若善上", Reverse("上善若水厚德载物"))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsLetter(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsLetter('a')
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExpand(b *testing.B) {
|
||||
match := map[string]string{
|
||||
"domain": "gowalker.org",
|
||||
"subdomain": "github.com",
|
||||
}
|
||||
s := "http://{domain}/{subdomain}/{0}/{1}"
|
||||
for i := 0; i < b.N; i++ {
|
||||
Expand(s, match, "Unknwon", "gowalker")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReverse(b *testing.B) {
|
||||
s := "abscef中文"
|
||||
for i := 0; i < b.N; i++ {
|
||||
Reverse(s)
|
||||
}
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
sudo: false
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
||||
|
||||
script: go test -v -cover -race
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- u@gogs.io
|
||||
+28
-22
@@ -32,7 +32,7 @@ import (
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
const _VERSION = "0.2.0"
|
||||
const _VERSION = "0.3.2"
|
||||
|
||||
func Version() string {
|
||||
return _VERSION
|
||||
@@ -145,7 +145,7 @@ func Form(formStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
|
||||
if parseErr != nil {
|
||||
errors.Add([]string{}, ERR_DESERIALIZATION, parseErr.Error())
|
||||
}
|
||||
mapForm(formStruct, ctx.Req.Form, nil, errors)
|
||||
errors = mapForm(formStruct, ctx.Req.Form, nil, errors)
|
||||
validateAndMap(formStruct, ctx, errors, ifacePtr...)
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ func MultipartForm(formStruct interface{}, ifacePtr ...interface{}) macaron.Hand
|
||||
ctx.Req.MultipartForm = form
|
||||
}
|
||||
}
|
||||
mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors)
|
||||
errors = mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors)
|
||||
validateAndMap(formStruct, ctx, errors, ifacePtr...)
|
||||
}
|
||||
}
|
||||
@@ -243,10 +243,10 @@ func Validate(obj interface{}) macaron.Handler {
|
||||
}
|
||||
|
||||
var (
|
||||
alphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
|
||||
alphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]")
|
||||
emailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
|
||||
urlPattern = regexp.MustCompile(`(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?`)
|
||||
AlphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
|
||||
AlphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]")
|
||||
EmailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
|
||||
URLPattern = regexp.MustCompile(`(http|https):\/\/(?:\\S+(?::\\S*)?@)?[\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?`)
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -255,7 +255,7 @@ type (
|
||||
// IsMatch checks if rule matches.
|
||||
IsMatch func(string) bool
|
||||
// IsValid applies validation rule to condition.
|
||||
IsValid func(Errors, string, interface{}) bool
|
||||
IsValid func(Errors, string, interface{}) (bool, Errors)
|
||||
}
|
||||
// RuleMapper represents a validation rule mapper,
|
||||
// it allwos users to add custom validation rules.
|
||||
@@ -361,12 +361,12 @@ VALIDATE_RULES:
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "AlphaDash":
|
||||
if alphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
if AlphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
errors.Add([]string{field.Name}, ERR_ALPHA_DASH, "AlphaDash")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "AlphaDashDot":
|
||||
if alphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
if AlphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
errors.Add([]string{field.Name}, ERR_ALPHA_DASH_DOT, "AlphaDashDot")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
@@ -414,7 +414,7 @@ VALIDATE_RULES:
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
case rule == "Email":
|
||||
if !emailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
if !EmailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
|
||||
errors.Add([]string{field.Name}, ERR_EMAIL, "Email")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
@@ -422,7 +422,7 @@ VALIDATE_RULES:
|
||||
str := fmt.Sprintf("%v", fieldValue)
|
||||
if len(str) == 0 {
|
||||
continue
|
||||
} else if !urlPattern.MatchString(str) {
|
||||
} else if !URLPattern.MatchString(str) {
|
||||
errors.Add([]string{field.Name}, ERR_URL, "Url")
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
@@ -449,7 +449,7 @@ VALIDATE_RULES:
|
||||
case strings.HasPrefix(rule, "Default("):
|
||||
if reflect.DeepEqual(zero, fieldValue) {
|
||||
if fieldVal.CanAddr() {
|
||||
setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors)
|
||||
errors = setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors)
|
||||
} else {
|
||||
errors.Add([]string{field.Name}, ERR_EXCLUDE, "Default")
|
||||
break VALIDATE_RULES
|
||||
@@ -457,9 +457,13 @@ VALIDATE_RULES:
|
||||
}
|
||||
default:
|
||||
// Apply custom validation rules.
|
||||
var isValid bool
|
||||
for i := range ruleMapper {
|
||||
if ruleMapper[i].IsMatch(rule) && !ruleMapper[i].IsValid(errors, field.Name, fieldValue) {
|
||||
break VALIDATE_RULES
|
||||
if ruleMapper[i].IsMatch(rule) {
|
||||
isValid, errors = ruleMapper[i].IsValid(errors, field.Name, fieldValue)
|
||||
if !isValid {
|
||||
break VALIDATE_RULES
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,7 +497,7 @@ func SetNameMapper(nm NameMapper) {
|
||||
|
||||
// Takes values from the form data and puts them into a struct
|
||||
func mapForm(formStruct reflect.Value, form map[string][]string,
|
||||
formfile map[string][]*multipart.FileHeader, errors Errors) {
|
||||
formfile map[string][]*multipart.FileHeader, errors Errors) Errors {
|
||||
|
||||
if formStruct.Kind() == reflect.Ptr {
|
||||
formStruct = formStruct.Elem()
|
||||
@@ -506,12 +510,12 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
|
||||
|
||||
if typeField.Type.Kind() == reflect.Ptr && typeField.Anonymous {
|
||||
structField.Set(reflect.New(typeField.Type.Elem()))
|
||||
mapForm(structField.Elem(), form, formfile, errors)
|
||||
errors = mapForm(structField.Elem(), form, formfile, errors)
|
||||
if reflect.DeepEqual(structField.Elem().Interface(), reflect.Zero(structField.Elem().Type()).Interface()) {
|
||||
structField.Set(reflect.Zero(structField.Type()))
|
||||
}
|
||||
} else if typeField.Type.Kind() == reflect.Struct {
|
||||
mapForm(structField, form, formfile, errors)
|
||||
errors = mapForm(structField, form, formfile, errors)
|
||||
}
|
||||
|
||||
inputFieldName := parseFormName(typeField.Name, typeField.Tag.Get("form"))
|
||||
@@ -526,11 +530,11 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
|
||||
sliceOf := structField.Type().Elem().Kind()
|
||||
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
|
||||
for i := 0; i < numElems; i++ {
|
||||
setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
|
||||
errors = setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
|
||||
}
|
||||
formStruct.Field(i).Set(slice)
|
||||
} else {
|
||||
setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors)
|
||||
errors = setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -551,13 +555,14 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
|
||||
structField.Set(reflect.ValueOf(inputFile[0]))
|
||||
}
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
// This sets the value in a struct of an indeterminate type to the
|
||||
// matching value from the request (via Form middleware) in the
|
||||
// same type, so that not all deserialized values have to be strings.
|
||||
// Supported types are string, int, float, and bool.
|
||||
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) {
|
||||
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) Errors {
|
||||
switch valueKind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if val == "" {
|
||||
@@ -582,7 +587,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
|
||||
case reflect.Bool:
|
||||
if val == "on" {
|
||||
structField.SetBool(true)
|
||||
return
|
||||
break
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
@@ -617,6 +622,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
|
||||
case reflect.String:
|
||||
structField.SetString(val)
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
// Don't pass in pointers to bind to. Can lead to bugs.
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
sudo: false
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
||||
|
||||
script: go test -v -cover -race
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- u@gogs.io
|
||||
+70
-10
@@ -50,6 +50,34 @@ type Invoker interface {
|
||||
Invoke(interface{}) ([]reflect.Value, error)
|
||||
}
|
||||
|
||||
// FastInvoker represents an interface in order to avoid the calling function via reflection.
|
||||
//
|
||||
// example:
|
||||
// type handlerFuncHandler func(http.ResponseWriter, *http.Request) error
|
||||
// func (f handlerFuncHandler)Invoke([]interface{}) ([]reflect.Value, error){
|
||||
// ret := f(p[0].(http.ResponseWriter), p[1].(*http.Request))
|
||||
// return []reflect.Value{reflect.ValueOf(ret)}, nil
|
||||
// }
|
||||
//
|
||||
// type funcHandler func(int, string)
|
||||
// func (f funcHandler)Invoke([]interface{}) ([]reflect.Value, error){
|
||||
// f(p[0].(int), p[1].(string))
|
||||
// return nil, nil
|
||||
// }
|
||||
type FastInvoker interface {
|
||||
// Invoke attempts to call the ordinary functions. If f is a function
|
||||
// with the appropriate signature, f.Invoke([]interface{}) is a Call that calls f.
|
||||
// Returns a slice of reflect.Value representing the returned values of the function.
|
||||
// Returns an error if the injection fails.
|
||||
Invoke([]interface{}) ([]reflect.Value, error)
|
||||
}
|
||||
|
||||
// IsFastInvoker check interface is FastInvoker
|
||||
func IsFastInvoker(h interface{}) bool {
|
||||
_, ok := h.(FastInvoker)
|
||||
return ok
|
||||
}
|
||||
|
||||
// TypeMapper represents an interface for mapping interface{} values based on type.
|
||||
type TypeMapper interface {
|
||||
// Maps the interface{} value based on its immediate type from reflect.TypeOf.
|
||||
@@ -102,18 +130,50 @@ func New() Injector {
|
||||
// It panics if f is not a function
|
||||
func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
|
||||
t := reflect.TypeOf(f)
|
||||
|
||||
var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
|
||||
for i := 0; i < t.NumIn(); i++ {
|
||||
argType := t.In(i)
|
||||
val := inj.GetVal(argType)
|
||||
if !val.IsValid() {
|
||||
return nil, fmt.Errorf("Value not found for type %v", argType)
|
||||
}
|
||||
|
||||
in[i] = val
|
||||
switch v := f.(type) {
|
||||
case FastInvoker:
|
||||
return inj.fastInvoke(v, t, t.NumIn())
|
||||
default:
|
||||
return inj.callInvoke(f, t, t.NumIn())
|
||||
}
|
||||
}
|
||||
|
||||
func (inj *injector) fastInvoke(f FastInvoker, t reflect.Type, numIn int) ([]reflect.Value, error) {
|
||||
var in []interface{}
|
||||
if numIn > 0 {
|
||||
in = make([]interface{}, numIn) // Panic if t is not kind of Func
|
||||
var argType reflect.Type
|
||||
var val reflect.Value
|
||||
for i := 0; i < numIn; i++ {
|
||||
argType = t.In(i)
|
||||
val = inj.GetVal(argType)
|
||||
if !val.IsValid() {
|
||||
return nil, fmt.Errorf("Value not found for type %v", argType)
|
||||
}
|
||||
|
||||
in[i] = val.Interface()
|
||||
}
|
||||
}
|
||||
return f.Invoke(in)
|
||||
}
|
||||
|
||||
// callInvoke reflect.Value.Call
|
||||
func (inj *injector) callInvoke(f interface{}, t reflect.Type, numIn int) ([]reflect.Value, error) {
|
||||
var in []reflect.Value
|
||||
if numIn > 0 {
|
||||
in = make([]reflect.Value, numIn)
|
||||
var argType reflect.Type
|
||||
var val reflect.Value
|
||||
for i := 0; i < numIn; i++ {
|
||||
argType = t.In(i)
|
||||
val = inj.GetVal(argType)
|
||||
if !val.IsValid() {
|
||||
return nil, fmt.Errorf("Value not found for type %v", argType)
|
||||
}
|
||||
|
||||
in[i] = val
|
||||
}
|
||||
}
|
||||
return reflect.ValueOf(f).Call(in), nil
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
ledis/tmp.db
|
||||
nodb/tmp.db
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
sudo: false
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
||||
|
||||
script: go test -v -cover -race
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- u@gogs.io
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# session [](https://travis-ci.org/go-macaron/session) [](http://gocover.io/github.com/go-macaron/session)
|
||||
# session [](https://travis-ci.org/go-macaron/session)
|
||||
|
||||
Middleware session provides session management for [Macaron](https://github.com/go-macaron/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
|
||||
|
||||
@@ -9,7 +9,7 @@ Middleware session provides session management for [Macaron](https://github.com/
|
||||
## Getting Help
|
||||
|
||||
- [API Reference](https://gowalker.org/github.com/go-macaron/session)
|
||||
- [Documentation](http://go-macaron.com/docs/middlewares/session)
|
||||
- [Documentation](https://go-macaron.com/docs/middlewares/session)
|
||||
|
||||
## Credits
|
||||
|
||||
|
||||
+6
-6
@@ -86,7 +86,7 @@ func (s *FileStore) Release() error {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(s.p.filepath(s.sid), data, os.ModePerm)
|
||||
return ioutil.WriteFile(s.p.filepath(s.sid), data, 0600)
|
||||
}
|
||||
|
||||
// Flush deletes all session data.
|
||||
@@ -121,7 +121,7 @@ func (p *FileProvider) filepath(sid string) string {
|
||||
// Read returns raw session store by session ID.
|
||||
func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
|
||||
filename := p.filepath(sid)
|
||||
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
|
||||
if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.lock.RLock()
|
||||
@@ -129,7 +129,7 @@ func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
|
||||
|
||||
var f *os.File
|
||||
if com.IsFile(filename) {
|
||||
f, err = os.OpenFile(filename, os.O_RDWR, os.ModePerm)
|
||||
f, err = os.OpenFile(filename, os.O_RDONLY, 0600)
|
||||
} else {
|
||||
f, err = os.Create(filename)
|
||||
}
|
||||
@@ -187,15 +187,15 @@ func (p *FileProvider) regenerate(oldsid, sid string) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.MkdirAll(path.Dir(oldname), os.ModePerm); err != nil {
|
||||
if err = os.MkdirAll(path.Dir(oldname), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ioutil.WriteFile(oldname, data, os.ModePerm); err != nil {
|
||||
if err = ioutil.WriteFile(oldname, data, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
|
||||
if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.Rename(oldname, filename); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user