mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
add a simple 'autofix' - most of the users need just an update
This commit is contained in:
parent
2a4ce876b6
commit
48c00f7cc2
193
autofix.go
Normal file
193
autofix.go
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
package iris
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
|
stdContext "context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/kataras/golog"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultModuleName = "app"
|
||||||
|
|
||||||
|
// simple function does not uses AST, it simply replaces import paths,
|
||||||
|
// creates a go.mod file if not exists and then run the `go mod tidy`
|
||||||
|
// command to remove old dependencies and install the new ones.
|
||||||
|
// It does NOT replaces breaking changes.
|
||||||
|
// The developer SHOULD visit the changelog(HISTORY.md) in order to learn
|
||||||
|
// everything about the new features and any breaking changes that comes with it.
|
||||||
|
func tryFix() error {
|
||||||
|
wdir, err := filepath.Abs(".") // should return the current directory (on both go run & executable).
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can not resolve current working directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// First of all, backup the current project,
|
||||||
|
// so any changes can be reverted by the end developer.
|
||||||
|
backupDest := wdir + "_irisbckp.zip"
|
||||||
|
golog.Infof("Backup <%s> to <%s>", wdir, backupDest)
|
||||||
|
|
||||||
|
err = zipDir(wdir, backupDest)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("backup dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// go module.
|
||||||
|
goModFile := filepath.Join(wdir, "go.mod")
|
||||||
|
if !fileExists(goModFile) {
|
||||||
|
|
||||||
|
golog.Warnf("Project is not a go module. Executing <go.mod init app>")
|
||||||
|
f, err := os.Create(goModFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("go.mod: %w", os.ErrNotExist)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(f, "module %s\ngo 1.15\n", defaultModuleName)
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// contnets replacements.
|
||||||
|
golog.Infof("Updating...") // note: we will not replace GOPATH project paths.
|
||||||
|
|
||||||
|
err = replaceDirContents(wdir, map[string]string{
|
||||||
|
`"github.com/kataras/iris`: `"github.com/kataras/iris/v12`,
|
||||||
|
// Note: we could use
|
||||||
|
// regexp's FindAllSubmatch, take the dir part and replace
|
||||||
|
// any HandleDir and e.t.c, but we are not going to do this.
|
||||||
|
// Look the comment of the tryFix() function.
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("replace import paths: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
commands := []string{
|
||||||
|
// "go clean --modcache",
|
||||||
|
"go env -w GOPROXY=https://goproxy.cn,https://gocenter.io,https://goproxy.io,direct",
|
||||||
|
"go mod tidy",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range commands {
|
||||||
|
if err = runCmd(wdir, c); err != nil {
|
||||||
|
// print out the command, especially
|
||||||
|
// with go env -w the user should know it.
|
||||||
|
// We use that because many of our users are living in China,
|
||||||
|
// which the default goproxy is blocked).
|
||||||
|
golog.Infof("$ %s", c)
|
||||||
|
return fmt.Errorf("command <%s>: %w", c, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileExists(path string) bool {
|
||||||
|
stat, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return os.IsExist(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return !stat.IsDir() && stat.Mode().IsRegular()
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCmd(wdir, c string) error {
|
||||||
|
ctx, cancel := stdContext.WithTimeout(stdContext.Background(), 2*time.Minute)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
parts := strings.Split(c, " ")
|
||||||
|
name, args := parts[0], parts[1:]
|
||||||
|
cmd := exec.CommandContext(ctx, name, args...)
|
||||||
|
// cmd.Path = wdir
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// zipDir zips a directory, recursively.
|
||||||
|
// It accepts a source directory and a destination zip file.
|
||||||
|
func zipDir(src, dest string) error {
|
||||||
|
folderName := filepath.Base(src)
|
||||||
|
|
||||||
|
file, err := os.Create(dest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
w := zip.NewWriter(file)
|
||||||
|
defer w.Close()
|
||||||
|
|
||||||
|
walkFunc := func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
relPath := filepath.Join(folderName, strings.TrimPrefix(path, src))
|
||||||
|
f, err := w.Create(relPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(f, file)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Walk(src, walkFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func replaceDirContents(target string, replacements map[string]string) error {
|
||||||
|
walkFunc := func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() || !info.Mode().IsRegular() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.OpenFile(path, os.O_RDWR, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
contents, ioErr := ioutil.ReadAll(file)
|
||||||
|
if ioErr != nil {
|
||||||
|
return ioErr
|
||||||
|
}
|
||||||
|
|
||||||
|
replaced := false
|
||||||
|
for oldContent, newContent := range replacements {
|
||||||
|
newContents := bytes.ReplaceAll(contents, []byte(oldContent), []byte(newContent))
|
||||||
|
if len(newContents) > 0 {
|
||||||
|
replaced = true
|
||||||
|
contents = newContents[0:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if replaced {
|
||||||
|
file.Truncate(0)
|
||||||
|
file.Seek(0, 0)
|
||||||
|
_, err = file.Write(contents)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Walk(target, walkFunc)
|
||||||
|
}
|
39
iris.go
39
iris.go
|
@ -22,6 +22,7 @@ import (
|
||||||
requestLogger "github.com/kataras/iris/middleware/logger"
|
requestLogger "github.com/kataras/iris/middleware/logger"
|
||||||
"github.com/kataras/iris/middleware/recover"
|
"github.com/kataras/iris/middleware/recover"
|
||||||
"github.com/kataras/iris/view"
|
"github.com/kataras/iris/view"
|
||||||
|
"github.com/kataras/pio"
|
||||||
|
|
||||||
"github.com/kataras/golog"
|
"github.com/kataras/golog"
|
||||||
"github.com/kataras/tunnel"
|
"github.com/kataras/tunnel"
|
||||||
|
@ -31,18 +32,38 @@ import (
|
||||||
const Version = "stale"
|
const Version = "stale"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
golog.Fatal(`You have installed an invalid version. Install with:
|
fmt.Println(`You have installed an invalid version. Install with:
|
||||||
go get -u github.com/kataras/iris/v12@latest
|
go get -u github.com/kataras/iris/v12@latest
|
||||||
|
|
||||||
If your Open Source project depends on that pre-go1.9 version please open an issue
|
If your Open Source project depends on that pre-go1.9 version please open an issue
|
||||||
at https://github.com/kataras/iris/issues/new and share your repository with us,
|
at https://github.com/kataras/iris/issues/new and share your repository with us,
|
||||||
we will upgrade your project's code base to the latest version for free.
|
we will upgrade your project's code base to the latest version for free.
|
||||||
|
|
||||||
If you have a commercial project that you cannot share publically, please contact with
|
If you have a commercial project that you cannot share publically, please contact with
|
||||||
@kataras at https://chat.iris-go.com. Assistance will be provided to you and your colleagues
|
@kataras at https://chat.iris-go.com. Assistance will be provided to you and your colleagues
|
||||||
for free.
|
for free.
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
fmt.Print("Run ")
|
||||||
|
pio.WriteRich(os.Stdout, "autofix", pio.Green, pio.Underline)
|
||||||
|
fmt.Print("? (Y/n): ")
|
||||||
|
var input string
|
||||||
|
_, err := fmt.Scanln(&input)
|
||||||
|
if err != nil {
|
||||||
|
golog.Fatalf("can not take input from user: %v", err)
|
||||||
|
}
|
||||||
|
input = strings.ToLower(input)
|
||||||
|
if input == "" || input == "y" {
|
||||||
|
err := tryFix()
|
||||||
|
if err != nil {
|
||||||
|
golog.Fatalf("autofix: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
golog.Infof("OK. Restart the application manually now.")
|
||||||
|
os.Exit(0)
|
||||||
|
} else {
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Byte unit helpers.
|
// Byte unit helpers.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user