2014-11-12 18:13:14 +03:00
|
|
|
// Copyright (c) 2014, B3log
|
2014-11-14 08:40:35 +03:00
|
|
|
//
|
2014-11-12 18:13:14 +03:00
|
|
|
// 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
|
2014-11-14 08:40:35 +03:00
|
|
|
//
|
2014-11-12 18:13:14 +03:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2014-11-14 08:40:35 +03:00
|
|
|
//
|
2014-11-12 18:13:14 +03:00
|
|
|
// 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.
|
|
|
|
|
2014-12-07 06:12:27 +03:00
|
|
|
// Package conf includes configurations related manipulations, all configurations (including user configurations) are
|
|
|
|
// stored in wide.json.
|
2014-08-18 17:45:43 +04:00
|
|
|
package conf
|
|
|
|
|
|
|
|
import (
|
2014-12-14 05:19:23 +03:00
|
|
|
"crypto/md5"
|
|
|
|
"encoding/hex"
|
2014-08-18 17:45:43 +04:00
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path/filepath"
|
2014-12-08 12:43:25 +03:00
|
|
|
"sort"
|
2014-11-18 11:56:33 +03:00
|
|
|
"strconv"
|
2014-08-18 17:45:43 +04:00
|
|
|
"strings"
|
2014-11-01 08:35:02 +03:00
|
|
|
"text/template"
|
2014-09-15 14:03:52 +04:00
|
|
|
"time"
|
2014-09-08 07:37:34 +04:00
|
|
|
|
2014-09-15 10:24:40 +04:00
|
|
|
"github.com/b3log/wide/event"
|
2014-12-13 13:47:41 +03:00
|
|
|
"github.com/b3log/wide/log"
|
2014-09-08 07:37:34 +04:00
|
|
|
"github.com/b3log/wide/util"
|
2014-08-18 17:45:43 +04:00
|
|
|
)
|
|
|
|
|
2014-10-21 06:47:16 +04:00
|
|
|
const (
|
2014-12-07 06:12:27 +03:00
|
|
|
// PathSeparator holds the OS-specific path separator.
|
|
|
|
PathSeparator = string(os.PathSeparator)
|
|
|
|
// PathListSeparator holds the OS-specific path list separator.
|
|
|
|
PathListSeparator = string(os.PathListSeparator)
|
2014-10-29 18:03:03 +03:00
|
|
|
)
|
2014-10-21 06:47:16 +04:00
|
|
|
|
2014-10-29 18:03:03 +03:00
|
|
|
const (
|
2014-12-07 06:12:27 +03:00
|
|
|
// WideVersion holds the current wide version.
|
2014-12-14 10:24:46 +03:00
|
|
|
WideVersion = "1.1.0"
|
2014-12-07 06:12:27 +03:00
|
|
|
// CodeMirrorVer holds the current editor version.
|
|
|
|
CodeMirrorVer = "4.8"
|
2014-10-21 06:47:16 +04:00
|
|
|
)
|
2014-10-13 10:34:42 +04:00
|
|
|
|
2014-12-07 06:12:27 +03:00
|
|
|
// LatestSessionContent represents the latest session content.
|
2014-09-22 19:13:07 +04:00
|
|
|
type LatestSessionContent struct {
|
2014-10-29 09:05:10 +03:00
|
|
|
FileTree []string // paths of expanding nodes of file tree
|
|
|
|
Files []string // paths of files of opening editor tabs
|
|
|
|
CurrentFile string // path of file of the current focused editor tab
|
2014-09-22 19:13:07 +04:00
|
|
|
}
|
|
|
|
|
2014-11-01 12:33:22 +03:00
|
|
|
// User configuration.
|
2014-08-31 14:50:38 +04:00
|
|
|
type User struct {
|
2014-09-22 19:13:07 +04:00
|
|
|
Name string
|
|
|
|
Password string
|
2014-12-08 09:02:39 +03:00
|
|
|
Email string
|
2014-12-14 05:19:23 +03:00
|
|
|
Gravatar string // see http://gravatar.com
|
2014-10-29 09:05:10 +03:00
|
|
|
Workspace string // the GOPATH of this user
|
2014-10-23 17:43:35 +04:00
|
|
|
Locale string
|
2014-10-26 13:08:01 +03:00
|
|
|
GoFormat string
|
2014-11-02 05:39:33 +03:00
|
|
|
FontFamily string
|
|
|
|
FontSize string
|
2014-11-30 05:18:17 +03:00
|
|
|
Theme string
|
2014-11-02 05:39:33 +03:00
|
|
|
Editor *Editor
|
2014-09-22 19:13:07 +04:00
|
|
|
LatestSessionContent *LatestSessionContent
|
2014-08-31 09:31:26 +04:00
|
|
|
}
|
|
|
|
|
2014-11-01 12:33:22 +03:00
|
|
|
// Editor configuration of a user.
|
2014-11-02 05:39:33 +03:00
|
|
|
type Editor struct {
|
|
|
|
FontFamily string
|
|
|
|
FontSize string
|
2014-11-14 08:40:35 +03:00
|
|
|
LineHeight string
|
2014-11-30 05:18:17 +03:00
|
|
|
Theme string
|
2014-12-01 09:49:16 +03:00
|
|
|
TabSize string
|
2014-11-01 12:33:22 +03:00
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// Configuration.
|
2014-08-23 19:07:24 +04:00
|
|
|
type conf struct {
|
2014-11-06 16:28:25 +03:00
|
|
|
IP string // server ip, ${ip}
|
2014-11-18 08:34:13 +03:00
|
|
|
Port string // server port
|
2014-12-11 10:32:24 +03:00
|
|
|
Context string // server context
|
2014-11-18 08:34:13 +03:00
|
|
|
Server string // server host and port ({IP}:{Port})
|
|
|
|
StaticServer string // static resources server scheme, host and port (http://{IP}:{Port})
|
2014-12-13 13:47:41 +03:00
|
|
|
LogLevel string // logging level
|
2014-12-11 10:32:24 +03:00
|
|
|
Channel string // channel (ws://{IP}:{Port})
|
2014-10-29 09:05:10 +03:00
|
|
|
HTTPSessionMaxAge int // HTTP session max age (in seciond)
|
|
|
|
StaticResourceVersion string // version of static resources
|
|
|
|
MaxProcs int // Go max procs
|
|
|
|
RuntimeMode string // runtime mode (dev/prod)
|
2014-11-06 16:28:25 +03:00
|
|
|
WD string // current working direcitory, ${pwd}
|
2014-10-29 09:05:10 +03:00
|
|
|
Locale string // default locale
|
|
|
|
Users []*User // configurations of users
|
2014-08-18 17:45:43 +04:00
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// Configuration variable.
|
2014-08-23 19:07:24 +04:00
|
|
|
var Wide conf
|
2014-09-22 19:13:07 +04:00
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// A raw copy of configuration variable.
|
2014-09-25 09:37:59 +04:00
|
|
|
//
|
2014-10-29 09:05:10 +03:00
|
|
|
// Save function will use this variable to persist.
|
2014-08-31 14:50:38 +04:00
|
|
|
var rawWide conf
|
2014-08-18 17:45:43 +04:00
|
|
|
|
2014-12-13 13:47:41 +03:00
|
|
|
// Logger.
|
|
|
|
var logger = log.NewLogger(os.Stdout)
|
|
|
|
|
2014-12-14 05:19:23 +03:00
|
|
|
// NewUser creates a user with the specified username, password, email and workspace.
|
|
|
|
func NewUser(username, password, email, workspace string) *User {
|
|
|
|
hash := md5.New()
|
|
|
|
hash.Write([]byte(email))
|
|
|
|
gravatar := hex.EncodeToString(hash.Sum(nil))
|
|
|
|
|
|
|
|
return &User{Name: username, Password: password, Email: email, Gravatar: gravatar, Workspace: workspace,
|
|
|
|
Locale: Wide.Locale, GoFormat: "gofmt", FontFamily: "Helvetica", FontSize: "13px", Theme: "default",
|
2014-12-14 12:43:46 +03:00
|
|
|
Editor: &Editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit", LineHeight: "17px",
|
|
|
|
Theme: "wide", TabSize: "4"}}
|
2014-12-14 05:19:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Load loads the configurations from wide.json.
|
|
|
|
func Load(confPath, confIP, confPort, confServer, confLogLevel, confStaticServer, confContext, confChannel string,
|
|
|
|
confDocker bool) {
|
|
|
|
bytes, _ := ioutil.ReadFile(confPath)
|
|
|
|
|
|
|
|
err := json.Unmarshal(bytes, &Wide)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error("Parses wide.json error: ", err)
|
|
|
|
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.SetLevel(Wide.LogLevel)
|
|
|
|
|
|
|
|
// keep the raw content
|
|
|
|
json.Unmarshal(bytes, &rawWide)
|
|
|
|
|
|
|
|
logger.Debug("Conf: \n" + string(bytes))
|
|
|
|
|
|
|
|
// Working Driectory
|
|
|
|
Wide.WD = util.OS.Pwd()
|
|
|
|
logger.Debugf("${pwd} [%s]", Wide.WD)
|
|
|
|
|
|
|
|
// IP
|
|
|
|
ip, err := util.Net.LocalIP()
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err)
|
|
|
|
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.Debugf("${ip} [%s]", ip)
|
|
|
|
|
|
|
|
if confDocker {
|
|
|
|
// TODO: may be we need to do something here
|
|
|
|
}
|
|
|
|
|
|
|
|
if "" != confIP {
|
|
|
|
ip = confIP
|
|
|
|
}
|
|
|
|
|
|
|
|
Wide.IP = strings.Replace(Wide.IP, "${ip}", ip, 1)
|
|
|
|
|
|
|
|
if "" != confPort {
|
|
|
|
Wide.Port = confPort
|
|
|
|
}
|
|
|
|
|
|
|
|
// Server
|
|
|
|
Wide.Server = strings.Replace(Wide.Server, "{IP}", Wide.IP, 1)
|
|
|
|
if "" != confServer {
|
|
|
|
Wide.Server = confServer
|
|
|
|
}
|
|
|
|
|
|
|
|
// Logging Level
|
|
|
|
if "" != confLogLevel {
|
|
|
|
Wide.LogLevel = confLogLevel
|
|
|
|
log.SetLevel(confLogLevel)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Static Server
|
|
|
|
Wide.StaticServer = strings.Replace(Wide.StaticServer, "{IP}", Wide.IP, 1)
|
|
|
|
if "" != confStaticServer {
|
|
|
|
Wide.StaticServer = confStaticServer
|
|
|
|
}
|
|
|
|
|
|
|
|
// Context
|
|
|
|
if "" != confContext {
|
|
|
|
Wide.Context = confContext
|
|
|
|
}
|
|
|
|
|
|
|
|
Wide.StaticResourceVersion = strings.Replace(Wide.StaticResourceVersion, "${time}", strconv.FormatInt(time.Now().UnixNano(), 10), 1)
|
|
|
|
|
|
|
|
// Channel
|
|
|
|
Wide.Channel = strings.Replace(Wide.Channel, "{IP}", Wide.IP, 1)
|
|
|
|
Wide.Channel = strings.Replace(Wide.Channel, "{Port}", Wide.Port, 1)
|
|
|
|
if "" != confChannel {
|
|
|
|
Wide.Channel = confChannel
|
|
|
|
}
|
|
|
|
|
|
|
|
Wide.Server = strings.Replace(Wide.Server, "{Port}", Wide.Port, 1)
|
|
|
|
Wide.StaticServer = strings.Replace(Wide.StaticServer, "{Port}", Wide.Port, 1)
|
|
|
|
|
|
|
|
// upgrade if need
|
|
|
|
upgrade()
|
|
|
|
|
|
|
|
initWorkspaceDirs()
|
|
|
|
initCustomizedConfs()
|
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// FixedTimeCheckEnv checks Wide runtime enviorment periodically (7 minutes).
|
2014-09-25 09:37:59 +04:00
|
|
|
//
|
2014-10-29 09:05:10 +03:00
|
|
|
// Exits process if found fatal issues (such as not found $GOPATH),
|
|
|
|
// Notifies user by notification queue if found warning issues (such as not found gocode).
|
2014-09-22 19:13:07 +04:00
|
|
|
func FixedTimeCheckEnv() {
|
2014-11-04 19:45:07 +03:00
|
|
|
checkEnv() // check immediately
|
|
|
|
|
2014-09-15 14:03:52 +04:00
|
|
|
go func() {
|
2014-10-10 10:24:47 +04:00
|
|
|
for _ = range time.Tick(time.Minute * 7) {
|
2014-11-04 19:45:07 +03:00
|
|
|
checkEnv()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2014-10-28 19:04:46 +03:00
|
|
|
|
2014-11-04 19:45:07 +03:00
|
|
|
func checkEnv() {
|
2014-11-26 06:07:06 +03:00
|
|
|
cmd := exec.Command("go", "version")
|
|
|
|
buf, err := cmd.CombinedOutput()
|
|
|
|
if nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error("Not found 'go' command, please make sure Go has been installed correctly")
|
2014-09-15 14:03:52 +04:00
|
|
|
|
2014-11-04 19:45:07 +03:00
|
|
|
os.Exit(-1)
|
|
|
|
}
|
2014-12-14 18:05:54 +03:00
|
|
|
logger.Trace(string(buf))
|
2014-10-28 19:04:46 +03:00
|
|
|
|
2014-11-26 06:07:06 +03:00
|
|
|
if "" == os.Getenv("GOPATH") {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error("Not found $GOPATH, please configure it before running Wide")
|
2014-09-15 14:03:52 +04:00
|
|
|
|
2014-11-04 19:45:07 +03:00
|
|
|
os.Exit(-1)
|
|
|
|
}
|
2014-10-28 19:04:46 +03:00
|
|
|
|
2014-11-26 06:54:01 +03:00
|
|
|
gocode := util.Go.GetExecutableInGOBIN("gocode")
|
2014-11-26 06:07:06 +03:00
|
|
|
cmd = exec.Command(gocode, "close")
|
|
|
|
_, err = cmd.Output()
|
2014-11-04 19:45:07 +03:00
|
|
|
if nil != err {
|
|
|
|
event.EventQueue <- &event.Event{Code: event.EvtCodeGocodeNotFound}
|
2014-09-15 14:03:52 +04:00
|
|
|
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Warnf("Not found gocode [%s]", gocode)
|
2014-11-04 19:45:07 +03:00
|
|
|
}
|
2014-10-28 19:04:46 +03:00
|
|
|
|
2014-12-07 06:12:27 +03:00
|
|
|
ideStub := util.Go.GetExecutableInGOBIN("ide_stub")
|
|
|
|
cmd = exec.Command(ideStub, "version")
|
2014-11-04 19:45:07 +03:00
|
|
|
_, err = cmd.Output()
|
|
|
|
if nil != err {
|
|
|
|
event.EventQueue <- &event.Event{Code: event.EvtCodeIDEStubNotFound}
|
|
|
|
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Warnf("Not found ide_stub [%s]", ideStub)
|
2014-11-04 19:45:07 +03:00
|
|
|
}
|
2014-09-22 19:13:07 +04:00
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// FixedTimeSave saves configurations (wide.json) periodically (1 minute).
|
2014-09-25 09:37:59 +04:00
|
|
|
//
|
2014-10-29 09:05:10 +03:00
|
|
|
// Main goal of this function is to save user session content, for restoring session content while user open Wide next time.
|
2014-09-22 19:13:07 +04:00
|
|
|
func FixedTimeSave() {
|
|
|
|
go func() {
|
2014-10-10 10:24:47 +04:00
|
|
|
for _ = range time.Tick(time.Minute) {
|
2014-09-22 19:13:07 +04:00
|
|
|
Save()
|
2014-09-15 14:03:52 +04:00
|
|
|
}
|
|
|
|
}()
|
2014-09-15 10:24:40 +04:00
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// GetUserWorkspace gets workspace path with the specified username, returns "" if not found.
|
2014-10-21 06:25:45 +04:00
|
|
|
func (c *conf) GetUserWorkspace(username string) string {
|
|
|
|
for _, user := range c.Users {
|
2014-09-13 12:50:18 +04:00
|
|
|
if user.Name == username {
|
2014-11-12 09:17:35 +03:00
|
|
|
return user.GetWorkspace()
|
2014-09-13 12:50:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ""
|
2014-09-05 07:24:53 +04:00
|
|
|
}
|
|
|
|
|
2014-11-26 06:54:01 +03:00
|
|
|
// GetGoFmt gets the path of Go format tool, returns "gofmt" if not found "goimports".
|
2014-10-26 13:08:01 +03:00
|
|
|
func (c *conf) GetGoFmt(username string) string {
|
|
|
|
for _, user := range c.Users {
|
|
|
|
if user.Name == username {
|
|
|
|
switch user.GoFormat {
|
|
|
|
case "gofmt":
|
|
|
|
return "gofmt"
|
|
|
|
case "goimports":
|
2014-11-26 06:54:01 +03:00
|
|
|
return util.Go.GetExecutableInGOBIN("goimports")
|
2014-10-26 13:08:01 +03:00
|
|
|
default:
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Errorf("Unsupported Go Format tool [%s]", user.GoFormat)
|
2014-10-26 13:08:01 +03:00
|
|
|
return "gofmt"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-30 12:27:01 +04:00
|
|
|
|
2014-10-26 13:08:01 +03:00
|
|
|
return "gofmt"
|
2014-09-30 12:27:01 +04:00
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// GetWorkspace gets workspace path of the user.
|
2014-10-28 05:57:16 +03:00
|
|
|
//
|
2014-10-29 09:05:10 +03:00
|
|
|
// Compared to the use of Wide.Workspace, this function will be processed as follows:
|
2014-11-06 16:28:25 +03:00
|
|
|
// 1. Replace {WD} variable with the actual directory path
|
2014-11-12 09:17:35 +03:00
|
|
|
// 2. Replace ${GOPATH} with enviorment variable GOPATH
|
|
|
|
// 3. Replace "/" with "\\" (Windows)
|
2014-10-28 05:57:16 +03:00
|
|
|
func (u *User) GetWorkspace() string {
|
2014-11-12 09:17:35 +03:00
|
|
|
w := strings.Replace(u.Workspace, "{WD}", Wide.WD, 1)
|
|
|
|
w = strings.Replace(w, "${GOPATH}", os.Getenv("GOPATH"), 1)
|
|
|
|
|
|
|
|
return filepath.FromSlash(w)
|
2014-10-28 05:57:16 +03:00
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// GetUser gets configuration of the user specified by the given username, returns nil if not found.
|
2014-09-23 18:29:53 +04:00
|
|
|
func (*conf) GetUser(username string) *User {
|
|
|
|
for _, user := range Wide.Users {
|
|
|
|
if user.Name == username {
|
|
|
|
return user
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// Save saves Wide configurations.
|
2014-08-31 14:50:38 +04:00
|
|
|
func Save() bool {
|
2014-10-29 09:05:10 +03:00
|
|
|
// just the Users field are volatile
|
2014-08-31 14:50:38 +04:00
|
|
|
rawWide.Users = Wide.Users
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// format
|
2014-08-31 14:50:38 +04:00
|
|
|
bytes, err := json.MarshalIndent(rawWide, "", " ")
|
|
|
|
|
|
|
|
if nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error(err)
|
2014-08-31 14:50:38 +04:00
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = ioutil.WriteFile("conf/wide.json", bytes, 0644); nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error(err)
|
2014-08-31 14:50:38 +04:00
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2014-11-30 05:18:17 +03:00
|
|
|
// upgrade upgrades the wide.json.
|
|
|
|
func upgrade() {
|
2014-12-11 10:32:24 +03:00
|
|
|
// Users
|
2014-11-30 05:18:17 +03:00
|
|
|
for _, user := range Wide.Users {
|
|
|
|
if "" == user.Theme {
|
|
|
|
user.Theme = "default" // since 1.1.0
|
|
|
|
}
|
|
|
|
|
|
|
|
if "" == user.Editor.Theme {
|
|
|
|
user.Editor.Theme = "wide" // since 1.1.0
|
|
|
|
}
|
2014-12-01 09:49:16 +03:00
|
|
|
|
|
|
|
if "" == user.Editor.TabSize {
|
|
|
|
user.Editor.TabSize = "4" // since 1.1.0
|
|
|
|
}
|
2014-12-14 05:19:23 +03:00
|
|
|
|
|
|
|
if "" != user.Email && "" == user.Gravatar {
|
|
|
|
hash := md5.New()
|
|
|
|
hash.Write([]byte(user.Email))
|
|
|
|
gravatar := hex.EncodeToString(hash.Sum(nil))
|
|
|
|
|
|
|
|
user.Gravatar = gravatar
|
|
|
|
}
|
2014-11-30 05:18:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Save()
|
|
|
|
}
|
|
|
|
|
2014-11-01 08:35:02 +03:00
|
|
|
// initCustomizedConfs initializes the user customized configurations.
|
|
|
|
func initCustomizedConfs() {
|
|
|
|
for _, user := range Wide.Users {
|
|
|
|
UpdateCustomizedConf(user.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateCustomizedConf creates (if not exists) or updates user customized configuration files.
|
|
|
|
//
|
|
|
|
// 1. /static/user/{username}/style.css
|
|
|
|
func UpdateCustomizedConf(username string) {
|
2014-12-07 06:12:27 +03:00
|
|
|
var u *User
|
2014-11-01 12:54:36 +03:00
|
|
|
for _, user := range Wide.Users { // maybe it is a beauty of the trade-off of the another world between design and implementation
|
2014-11-01 12:33:22 +03:00
|
|
|
if user.Name == username {
|
|
|
|
u = user
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if nil == u {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2014-11-02 05:39:33 +03:00
|
|
|
model := map[string]interface{}{"user": u}
|
2014-11-01 08:35:02 +03:00
|
|
|
|
|
|
|
t, err := template.ParseFiles("static/user/style.css.tmpl")
|
|
|
|
if nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error(err)
|
2014-11-01 08:35:02 +03:00
|
|
|
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
wd := util.OS.Pwd()
|
2014-11-01 12:33:22 +03:00
|
|
|
dir := filepath.Clean(wd + "/static/user/" + u.Name)
|
2014-11-12 05:41:27 +03:00
|
|
|
if err := os.MkdirAll(dir, 0755); nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error(err)
|
2014-11-01 08:35:02 +03:00
|
|
|
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
fout, err := os.Create(dir + PathSeparator + "style.css")
|
|
|
|
if nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error(err)
|
2014-11-01 08:35:02 +03:00
|
|
|
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer fout.Close()
|
|
|
|
|
2014-11-01 12:45:43 +03:00
|
|
|
if err := t.Execute(fout, model); nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error(err)
|
2014-11-01 12:45:43 +03:00
|
|
|
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
2014-10-28 05:57:16 +03:00
|
|
|
}
|
|
|
|
|
2014-11-12 09:49:14 +03:00
|
|
|
// initWorkspaceDirs initializes the directories of users' workspaces.
|
2014-10-28 05:57:16 +03:00
|
|
|
//
|
2014-10-29 09:05:10 +03:00
|
|
|
// Creates directories if not found on path of workspace.
|
2014-10-28 05:57:16 +03:00
|
|
|
func initWorkspaceDirs() {
|
2014-11-12 09:49:14 +03:00
|
|
|
paths := []string{}
|
2014-10-28 05:57:16 +03:00
|
|
|
|
|
|
|
for _, user := range Wide.Users {
|
2014-10-28 08:22:39 +03:00
|
|
|
paths = append(paths, filepath.SplitList(user.GetWorkspace())...)
|
2014-10-28 05:57:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, path := range paths {
|
2014-10-29 18:03:03 +03:00
|
|
|
CreateWorkspaceDir(path)
|
2014-10-28 05:57:16 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-01 08:35:02 +03:00
|
|
|
// CreateWorkspaceDir creates (if not exists) directories on the path.
|
2014-10-28 05:57:16 +03:00
|
|
|
//
|
2014-10-29 09:05:10 +03:00
|
|
|
// 1. root directory:{path}
|
|
|
|
// 2. src directory: {path}/src
|
|
|
|
// 3. package directory: {path}/pkg
|
|
|
|
// 4. binary directory: {path}/bin
|
2014-10-29 18:03:03 +03:00
|
|
|
func CreateWorkspaceDir(path string) {
|
2014-10-28 05:57:16 +03:00
|
|
|
createDir(path)
|
|
|
|
createDir(path + PathSeparator + "src")
|
|
|
|
createDir(path + PathSeparator + "pkg")
|
|
|
|
createDir(path + PathSeparator + "bin")
|
|
|
|
}
|
|
|
|
|
2014-10-29 09:05:10 +03:00
|
|
|
// createDir creates a directory on the path if it not exists.
|
2014-10-28 05:57:16 +03:00
|
|
|
func createDir(path string) {
|
2014-11-16 11:25:27 +03:00
|
|
|
if !util.File.IsExist(path) {
|
2014-10-28 05:57:16 +03:00
|
|
|
if err := os.MkdirAll(path, 0775); nil != err {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Error(err)
|
2014-10-28 05:57:16 +03:00
|
|
|
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
}
|
2014-08-18 17:45:43 +04:00
|
|
|
}
|
2014-11-30 05:18:17 +03:00
|
|
|
|
|
|
|
// GetEditorThemes gets the names of editor themes.
|
|
|
|
func GetEditorThemes() []string {
|
|
|
|
ret := []string{}
|
|
|
|
|
|
|
|
f, _ := os.Open("static/js/overwrite/codemirror" + "/theme")
|
|
|
|
names, _ := f.Readdirnames(-1)
|
|
|
|
f.Close()
|
|
|
|
|
|
|
|
for _, name := range names {
|
|
|
|
ret = append(ret, name[:strings.LastIndex(name, ".")])
|
|
|
|
}
|
|
|
|
|
2014-12-08 12:43:25 +03:00
|
|
|
sort.Strings(ret)
|
|
|
|
|
2014-11-30 05:18:17 +03:00
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetThemes gets the names of themes.
|
|
|
|
func GetThemes() []string {
|
|
|
|
ret := []string{}
|
|
|
|
|
|
|
|
f, _ := os.Open("static/css/themes")
|
|
|
|
names, _ := f.Readdirnames(-1)
|
|
|
|
f.Close()
|
|
|
|
|
|
|
|
for _, name := range names {
|
|
|
|
ret = append(ret, name[:strings.LastIndex(name, ".")])
|
|
|
|
}
|
|
|
|
|
2014-12-08 12:43:25 +03:00
|
|
|
sort.Strings(ret)
|
|
|
|
|
2014-11-30 05:18:17 +03:00
|
|
|
return ret
|
|
|
|
}
|