mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
fix setting of readonly vars issue with zsh rc files
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
|
||||
"github.com/alessio/shellescape"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
||||
@@ -105,6 +106,7 @@ var localZshMajorVersion = ""
|
||||
|
||||
// sentinel value for functions that should be autoloaded
|
||||
const ZshFnAutoLoad = "autoload"
|
||||
const ZshAutoloadFnBody = "builtin autoload -XU"
|
||||
|
||||
type ZshParamKey struct {
|
||||
// paramtype cannot contain spaces
|
||||
@@ -204,6 +206,19 @@ func makeZshTypesetStmt(varDecl *shellenv.DeclareDeclType) string {
|
||||
}
|
||||
}
|
||||
|
||||
func isZshSafeNameStr(name string) bool {
|
||||
for _, ch := range name {
|
||||
if ch == '_' {
|
||||
continue
|
||||
}
|
||||
if unicode.IsLetter(ch) || unicode.IsDigit(ch) {
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (z zshShellApi) MakeRcFileStr(pk *packet.RunPacketType) string {
|
||||
var rcBuf bytes.Buffer
|
||||
rcBuf.WriteString(z.GetBaseShellOpts() + "\n")
|
||||
@@ -216,9 +231,6 @@ func (z zshShellApi) MakeRcFileStr(pk *packet.RunPacketType) string {
|
||||
if ZshIgnoreVars[varDecl.Name] {
|
||||
continue
|
||||
}
|
||||
if varDecl.IsReadOnly() {
|
||||
continue
|
||||
}
|
||||
if ZshUniqueArrayVars[varDecl.Name] && !varDecl.IsUniqueArray() {
|
||||
varDecl.AddFlag("U")
|
||||
}
|
||||
@@ -230,7 +242,19 @@ func (z zshShellApi) MakeRcFileStr(pk *packet.RunPacketType) string {
|
||||
if stmt == "" {
|
||||
continue
|
||||
}
|
||||
rcBuf.WriteString(makeZshTypesetStmt(varDecl))
|
||||
if varDecl.IsReadOnly() {
|
||||
// we can't reset read-only variables
|
||||
// so we check if it is a "safe" name, and then we can write a conditional
|
||||
// that only sets it if it hasn't already been set.
|
||||
if !isZshSafeNameStr(varDecl.Name) {
|
||||
continue
|
||||
}
|
||||
rcBuf.WriteString(fmt.Sprintf("if (( ! ${+%s} )); then\n", varDecl.Name))
|
||||
rcBuf.WriteString(makeZshTypesetStmt(varDecl))
|
||||
rcBuf.WriteString("\nfi")
|
||||
} else {
|
||||
rcBuf.WriteString(makeZshTypesetStmt(varDecl))
|
||||
}
|
||||
rcBuf.WriteString("\n")
|
||||
}
|
||||
if shellenv.FindVarDecl(varDecls, "ZDOTDIR") == nil {
|
||||
@@ -519,6 +543,8 @@ func ParseZshFunctions(fpathArr []string, fnBytes []byte, partSeparator []byte)
|
||||
source := fnSource[fnKey.ParamName]
|
||||
if isSourceFileInFpath(fpathArr, source) {
|
||||
fnBody[fnKey] = ZshFnAutoLoad
|
||||
} else if strings.TrimSpace(fnBody[fnKey]) == ZshAutoloadFnBody {
|
||||
fnBody[fnKey] = ZshFnAutoLoad
|
||||
}
|
||||
}
|
||||
return fnBody
|
||||
|
||||
@@ -27,3 +27,21 @@ func TestParseZshDecl(t *testing.T) {
|
||||
declStr = `typeset -x -g -aT FOO foo=( 1 2 3 )`
|
||||
testSingleDecl(declStr)
|
||||
}
|
||||
|
||||
func TestZshSafeDeclName(t *testing.T) {
|
||||
if !isZshSafeNameStr("foo") {
|
||||
t.Errorf("foo should be safe")
|
||||
}
|
||||
if isZshSafeNameStr("foo bar") {
|
||||
t.Errorf("foo bar should not be safe")
|
||||
}
|
||||
if !isZshSafeNameStr("foo_bar") {
|
||||
t.Errorf("foo_bar should be safe")
|
||||
}
|
||||
if !isZshSafeNameStr("été") {
|
||||
t.Errorf("été should be be safe")
|
||||
}
|
||||
if isZshSafeNameStr("hello\x01z") {
|
||||
t.Errorf("should not be safe")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ const ShellVarName = "SHELL"
|
||||
const SigKillWaitTime = 2 * time.Second
|
||||
const RtnStateFdNum = 20
|
||||
const ReturnStateReadWaitTime = 2 * time.Second
|
||||
const ForceDebugRcFile = false
|
||||
|
||||
const ClientCommandFmt = `
|
||||
PATH=$PATH:~/.mshell;
|
||||
@@ -821,7 +822,7 @@ func RunCommandSimple(pk *packet.RunPacketType, sender *packet.PacketSender, fro
|
||||
rcFileStr += trapCmdStr
|
||||
}
|
||||
shellVarMap := shellenv.ShellVarMapFromState(state)
|
||||
if base.HasDebugFlag(shellVarMap, base.DebugFlag_LogRcFile) {
|
||||
if base.HasDebugFlag(shellVarMap, base.DebugFlag_LogRcFile) || ForceDebugRcFile {
|
||||
debugRcFileName := base.GetDebugRcFileName()
|
||||
err := os.WriteFile(debugRcFileName, []byte(rcFileStr), 0600)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user