Replace os.Rename with directory copy util in plugin extraction (#7825)
Этот коммит содержится в:
коммит произвёл
Christopher Speller
родитель
120fbed0f7
Коммит
79726b5d8e
@@ -358,7 +358,7 @@ func (a *App) InstallPlugin(pluginFile io.Reader) (*model.Manifest, *model.AppEr
|
|||||||
return nil, model.NewAppError("UnpackAndActivatePlugin", "app.plugin.manifest.app_error", nil, err.Error(), http.StatusBadRequest)
|
return nil, model.NewAppError("UnpackAndActivatePlugin", "app.plugin.manifest.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Rename(tmpPluginDir, filepath.Join(a.PluginEnv.SearchPath(), manifest.Id))
|
err = utils.CopyDir(tmpPluginDir, filepath.Join(a.PluginEnv.SearchPath(), manifest.Id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, model.NewAppError("UnpackAndActivatePlugin", "app.plugin.mvdir.app_error", nil, err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("UnpackAndActivatePlugin", "app.plugin.mvdir.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|||||||
101
utils/file.go
101
utils/file.go
@@ -5,6 +5,8 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@@ -367,3 +369,102 @@ func CopyMetadata(encrypt bool) map[string]string {
|
|||||||
metaData["x-amz-server-side-encryption"] = "AES256"
|
metaData["x-amz-server-side-encryption"] = "AES256"
|
||||||
return metaData
|
return metaData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CopyFile will copy a file from src path to dst path.
|
||||||
|
// Overwrites any existing files at dst.
|
||||||
|
// Permissions are copied from file at src to the new file at dst.
|
||||||
|
func CopyFile(src, dst string) (err error) {
|
||||||
|
in, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer in.Close()
|
||||||
|
|
||||||
|
out, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if e := out.Close(); e != nil {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err = io.Copy(out, in)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = out.Sync()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stat, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Chmod(dst, stat.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyDir will copy a directory and all contained files and directories.
|
||||||
|
// src must exist and dst must not exist.
|
||||||
|
// Permissions are preserved when possible. Symlinks are skipped.
|
||||||
|
func CopyDir(src string, dst string) (err error) {
|
||||||
|
src = filepath.Clean(src)
|
||||||
|
dst = filepath.Clean(dst)
|
||||||
|
|
||||||
|
stat, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !stat.IsDir() {
|
||||||
|
return fmt.Errorf("source must be a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = os.Stat(dst)
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("destination already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(dst, stat.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
items, err := ioutil.ReadDir(src)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range items {
|
||||||
|
srcPath := filepath.Join(src, item.Name())
|
||||||
|
dstPath := filepath.Join(dst, item.Name())
|
||||||
|
|
||||||
|
if item.IsDir() {
|
||||||
|
err = CopyDir(srcPath, dstPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if item.Mode()&os.ModeSymlink != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CopyFile(srcPath, dstPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
@@ -180,3 +184,53 @@ func (s *FileTestSuite) TestRemoveDirectory() {
|
|||||||
_, err = ReadFile("tests2/asdf")
|
_, err = ReadFile("tests2/asdf")
|
||||||
s.Error(err)
|
s.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCopyDir(t *testing.T) {
|
||||||
|
srcDir, err := ioutil.TempDir("", "src")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(srcDir)
|
||||||
|
|
||||||
|
dstParentDir, err := ioutil.TempDir("", "dstparent")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(dstParentDir)
|
||||||
|
|
||||||
|
dstDir := filepath.Join(dstParentDir, "dst")
|
||||||
|
|
||||||
|
tempFile := "temp.txt"
|
||||||
|
err = ioutil.WriteFile(filepath.Join(srcDir, tempFile), []byte("test file"), 0655)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
childDir := "child"
|
||||||
|
err = os.Mkdir(filepath.Join(srcDir, childDir), 0777)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
childTempFile := "childtemp.txt"
|
||||||
|
err = ioutil.WriteFile(filepath.Join(srcDir, childDir, childTempFile), []byte("test file"), 0755)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = CopyDir(srcDir, dstDir)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
stat, err := os.Stat(filepath.Join(dstDir, tempFile))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, uint32(0655), uint32(stat.Mode()))
|
||||||
|
assert.False(t, stat.IsDir())
|
||||||
|
data, err := ioutil.ReadFile(filepath.Join(dstDir, tempFile))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test file", string(data))
|
||||||
|
|
||||||
|
stat, err = os.Stat(filepath.Join(dstDir, childDir))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, stat.IsDir())
|
||||||
|
|
||||||
|
stat, err = os.Stat(filepath.Join(dstDir, childDir, childTempFile))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, uint32(0755), uint32(stat.Mode()))
|
||||||
|
assert.False(t, stat.IsDir())
|
||||||
|
data, err = ioutil.ReadFile(filepath.Join(dstDir, childDir, childTempFile))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test file", string(data))
|
||||||
|
|
||||||
|
err = CopyDir(srcDir, dstDir)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user