This reverts commit d3cf110620.
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
d3cf110620
Коммит
2f6039f23f
@@ -6,11 +6,20 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func findMattermostBinary() string {
|
||||||
|
for _, file := range []string{"./mattermost", "../mattermost", "./bin/mattermost"} {
|
||||||
|
path, _ := filepath.Abs(file)
|
||||||
|
if stat, err := os.Stat(path); err == nil && !stat.IsDir() {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "./mattermost"
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Print angry message to use mattermost command directly
|
// Print angry message to use mattermost command directly
|
||||||
fmt.Println(`
|
fmt.Println(`
|
||||||
@@ -24,14 +33,7 @@ The platform binary will be removed in a future version.
|
|||||||
args := os.Args
|
args := os.Args
|
||||||
args[0] = "mattermost"
|
args[0] = "mattermost"
|
||||||
args = append(args, "--platform")
|
args = append(args, "--platform")
|
||||||
|
if err := syscall.Exec(findMattermostBinary(), args, nil); err != nil {
|
||||||
realMattermost := utils.FindFile("mattermost")
|
|
||||||
if realMattermost == "" {
|
|
||||||
// This will still fail, of course.
|
|
||||||
realMattermost = "./mattermost"
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := syscall.Exec(utils.FindFile("mattermost"), args, nil); err != nil {
|
|
||||||
fmt.Println("Could not start Mattermost, use the mattermost command directly.")
|
fmt.Println("Could not start Mattermost, use the mattermost command directly.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
100
utils/config.go
100
utils/config.go
@@ -32,94 +32,36 @@ const (
|
|||||||
LOG_FILENAME = "mattermost.log"
|
LOG_FILENAME = "mattermost.log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
commonBaseSearchPaths = []string{
|
|
||||||
".",
|
|
||||||
"..",
|
|
||||||
"../..",
|
|
||||||
"../../..",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func FindPath(path string, baseSearchPaths []string, filter func(os.FileInfo) bool) string {
|
|
||||||
if filepath.IsAbs(path) {
|
|
||||||
if _, err := os.Stat(path); err == nil {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
searchPaths := []string{}
|
|
||||||
for _, baseSearchPath := range baseSearchPaths {
|
|
||||||
searchPaths = append(searchPaths, baseSearchPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additionally attempt to search relative to the location of the running binary.
|
|
||||||
var binaryDir string
|
|
||||||
if exe, err := os.Executable(); err == nil {
|
|
||||||
if exe, err = filepath.EvalSymlinks(exe); err == nil {
|
|
||||||
if exe, err = filepath.Abs(exe); err == nil {
|
|
||||||
binaryDir = filepath.Dir(exe)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if binaryDir != "" {
|
|
||||||
for _, baseSearchPath := range baseSearchPaths {
|
|
||||||
searchPaths = append(
|
|
||||||
searchPaths,
|
|
||||||
filepath.Join(binaryDir, baseSearchPath),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, parent := range searchPaths {
|
|
||||||
found, err := filepath.Abs(filepath.Join(parent, path))
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
} else if fileInfo, err := os.Stat(found); err == nil {
|
|
||||||
if filter != nil && filter(fileInfo) {
|
|
||||||
return found
|
|
||||||
} else {
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindConfigFile attempts to find an existing configuration file. fileName can be an absolute or
|
// FindConfigFile attempts to find an existing configuration file. fileName can be an absolute or
|
||||||
// relative path or name such as "/opt/mattermost/config.json" or simply "config.json". An empty
|
// relative path or name such as "/opt/mattermost/config.json" or simply "config.json". An empty
|
||||||
// string is returned if no configuration is found.
|
// string is returned if no configuration is found.
|
||||||
func FindConfigFile(fileName string) (path string) {
|
func FindConfigFile(fileName string) (path string) {
|
||||||
found := FindFile(filepath.Join("config", fileName))
|
if filepath.IsAbs(fileName) {
|
||||||
if found == "" {
|
if _, err := os.Stat(fileName); err == nil {
|
||||||
found = FindPath(fileName, []string{"."}, nil)
|
return fileName
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, dir := range []string{"./config", "../config", "../../config", "../../../config", "."} {
|
||||||
|
path, _ := filepath.Abs(filepath.Join(dir, fileName))
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
return found
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindFile looks for the given file in nearby ancestors relative to the current working
|
// FindDir looks for the given directory in nearby ancestors, falling back to `./` if not found.
|
||||||
// directory as well as the directory of the executable.
|
|
||||||
func FindFile(path string) string {
|
|
||||||
return FindPath(path, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
|
|
||||||
return !fileInfo.IsDir()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindDir looks for the given directory in nearby ancestors relative to the current working
|
|
||||||
// directory as well as the directory of the executable, falling back to `./` if not found.
|
|
||||||
func FindDir(dir string) (string, bool) {
|
func FindDir(dir string) (string, bool) {
|
||||||
found := FindPath(dir, commonBaseSearchPaths, func(fileInfo os.FileInfo) bool {
|
for _, parent := range []string{".", "..", "../..", "../../.."} {
|
||||||
return fileInfo.IsDir()
|
foundDir, err := filepath.Abs(filepath.Join(parent, dir))
|
||||||
})
|
if err != nil {
|
||||||
if found == "" {
|
continue
|
||||||
return "./", false
|
} else if _, err := os.Stat(foundDir); err == nil {
|
||||||
|
return foundDir, true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return "./", false
|
||||||
return found, true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MloggerConfigFromLoggerConfig(s *model.LogSettings) *mlog.LoggerConfiguration {
|
func MloggerConfigFromLoggerConfig(s *model.LogSettings) *mlog.LoggerConfiguration {
|
||||||
|
|||||||
@@ -46,172 +46,20 @@ func TestTimezoneConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindConfigFile(t *testing.T) {
|
func TestFindConfigFile(t *testing.T) {
|
||||||
t.Run("config.json in current working directory, not inside config/", func(t *testing.T) {
|
dir, err := ioutil.TempDir("", "")
|
||||||
// Force a unique working directory
|
require.NoError(t, err)
|
||||||
cwd, err := ioutil.TempDir("", "")
|
defer os.RemoveAll(dir)
|
||||||
require.NoError(t, err)
|
|
||||||
defer os.RemoveAll(cwd)
|
|
||||||
|
|
||||||
prevDir, err := os.Getwd()
|
path := filepath.Join(dir, "config.json")
|
||||||
require.NoError(t, err)
|
require.NoError(t, ioutil.WriteFile(path, []byte("{}"), 0600))
|
||||||
defer os.Chdir(prevDir)
|
|
||||||
os.Chdir(cwd)
|
|
||||||
|
|
||||||
configJson, err := filepath.Abs("config.json")
|
assert.Equal(t, path, FindConfigFile(path))
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, ioutil.WriteFile(configJson, []byte("{}"), 0600))
|
|
||||||
|
|
||||||
// Relative paths end up getting symlinks fully resolved.
|
prevDir, err := os.Getwd()
|
||||||
configJsonResolved, err := filepath.EvalSymlinks(configJson)
|
require.NoError(t, err)
|
||||||
require.NoError(t, err)
|
defer os.Chdir(prevDir)
|
||||||
|
os.Chdir(dir)
|
||||||
assert.Equal(t, configJsonResolved, FindConfigFile("config.json"))
|
assert.Equal(t, path, FindConfigFile(path))
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("config/config.json from various paths", func(t *testing.T) {
|
|
||||||
// Create the following directory structure:
|
|
||||||
// tmpDir1/
|
|
||||||
// config/
|
|
||||||
// config.json
|
|
||||||
// tmpDir2/
|
|
||||||
// tmpDir3/
|
|
||||||
// tmpDir4/
|
|
||||||
// tmpDir5/
|
|
||||||
tmpDir1, err := ioutil.TempDir("", "")
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer os.RemoveAll(tmpDir1)
|
|
||||||
|
|
||||||
err = os.Mkdir(filepath.Join(tmpDir1, "config"), 0700)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
tmpDir2, err := ioutil.TempDir(tmpDir1, "")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
tmpDir3, err := ioutil.TempDir(tmpDir2, "")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
tmpDir4, err := ioutil.TempDir(tmpDir3, "")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
tmpDir5, err := ioutil.TempDir(tmpDir4, "")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
configJson := filepath.Join(tmpDir1, "config", "config.json")
|
|
||||||
require.NoError(t, ioutil.WriteFile(configJson, []byte("{}"), 0600))
|
|
||||||
|
|
||||||
// Relative paths end up getting symlinks fully resolved, so use this below as necessary.
|
|
||||||
configJsonResolved, err := filepath.EvalSymlinks(configJson)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
Description string
|
|
||||||
Cwd *string
|
|
||||||
FileName string
|
|
||||||
Expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"absolute path to config.json",
|
|
||||||
nil,
|
|
||||||
configJson,
|
|
||||||
configJson,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"absolute path to config.json from directory containing config.json",
|
|
||||||
&tmpDir1,
|
|
||||||
configJson,
|
|
||||||
configJson,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"relative path to config.json from directory containing config.json",
|
|
||||||
&tmpDir1,
|
|
||||||
"config.json",
|
|
||||||
configJsonResolved,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"subdirectory of directory containing config.json",
|
|
||||||
&tmpDir2,
|
|
||||||
"config.json",
|
|
||||||
configJsonResolved,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"twice-nested subdirectory of directory containing config.json",
|
|
||||||
&tmpDir3,
|
|
||||||
"config.json",
|
|
||||||
configJsonResolved,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"thrice-nested subdirectory of directory containing config.json",
|
|
||||||
&tmpDir4,
|
|
||||||
"config.json",
|
|
||||||
configJsonResolved,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"can't find from four nesting levels deep",
|
|
||||||
&tmpDir5,
|
|
||||||
"config.json",
|
|
||||||
"",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
t.Run(testCase.Description, func(t *testing.T) {
|
|
||||||
if testCase.Cwd != nil {
|
|
||||||
prevDir, err := os.Getwd()
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer os.Chdir(prevDir)
|
|
||||||
os.Chdir(*testCase.Cwd)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, testCase.Expected, FindConfigFile(testCase.FileName))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("config/config.json relative to executable", func(t *testing.T) {
|
|
||||||
osExecutable, err := os.Executable()
|
|
||||||
require.NoError(t, err)
|
|
||||||
osExecutableDir := filepath.Dir(osExecutable)
|
|
||||||
|
|
||||||
// Force a working directory different than the executable.
|
|
||||||
cwd, err := ioutil.TempDir("", "")
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer os.RemoveAll(cwd)
|
|
||||||
|
|
||||||
prevDir, err := os.Getwd()
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer os.Chdir(prevDir)
|
|
||||||
os.Chdir(cwd)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
Description string
|
|
||||||
RelativePath string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"config/config.json",
|
|
||||||
".",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"../config/config.json",
|
|
||||||
"../",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
t.Run(testCase.Description, func(t *testing.T) {
|
|
||||||
// Install the config in config/config.json relative to the executable
|
|
||||||
configJson := filepath.Join(osExecutableDir, testCase.RelativePath, "config", "config.json")
|
|
||||||
require.NoError(t, os.Mkdir(filepath.Dir(configJson), 0700))
|
|
||||||
require.NoError(t, ioutil.WriteFile(configJson, []byte("{}"), 0600))
|
|
||||||
defer os.RemoveAll(filepath.Dir(configJson))
|
|
||||||
|
|
||||||
// Relative paths end up getting symlinks fully resolved.
|
|
||||||
configJsonResolved, err := filepath.EvalSymlinks(configJson)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, configJsonResolved, FindConfigFile("config.json"))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConfigFromEnviroVars(t *testing.T) {
|
func TestConfigFromEnviroVars(t *testing.T) {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user