diff --git a/cmd/defender/defender.go b/cmd/defender/defender.go new file mode 100644 index 000000000..0adf59140 --- /dev/null +++ b/cmd/defender/defender.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" + "os" + + "github.com/goplus/gop/defender" +) + +func main() { + if len(os.Args) < 2 { + fmt.Println("Start processing, please wait for a moment ...") + if err := defender.Exclude(); err != nil { + fmt.Println(err) + } + return + } + switch os.Args[1] { + case "add": + fmt.Println("Start processing, please wait for a moment ...") + if err := defender.Exclude(); err != nil { + fmt.Println(err) + } + case "remove": + fmt.Println("Start processing, please wait for a moment ...") + if err := defender.Remove(); err != nil { + fmt.Println(err) + } + default: + fmt.Println("expected 'add' or 'remove' subcommands") + os.Exit(1) + } +} diff --git a/cmd/make.go b/cmd/make.go index 6ecf458a6..f150f313d 100644 --- a/cmd/make.go +++ b/cmd/make.go @@ -31,6 +31,8 @@ import ( "runtime" "strings" "time" + + "github.com/goplus/gop/defender" ) func checkPathExist(path string, isDir bool) bool { @@ -379,6 +381,8 @@ we recommend you add the above install directory into your PATH environment vari func install() { installPath := linkGoplusToLocalBin() + defender.Exclude() + println("\nGo+ tools installed successfully!") if _, err := execCommand("gop", "version"); err != nil { @@ -407,6 +411,9 @@ func runTestcases() { } func clean() { + + defender.Remove() + gopBinPath := detectGopBinPath() goBinPath := detectGoBinPath() diff --git a/defender/cmdstr.go b/defender/cmdstr.go new file mode 100644 index 000000000..6e48ab55f --- /dev/null +++ b/defender/cmdstr.go @@ -0,0 +1,11 @@ +package defender + +import "fmt" + +func excludeDirString(excludeDir string) string { + return fmt.Sprintf("Add-MpPreference -ExclusionPath '%s'", excludeDir) +} + +func excludeExtString(excludeExt string) string { + return fmt.Sprintf("Add-MpPreference -ExclusionExtension '%s'", excludeExt) +} diff --git a/defender/defender.go b/defender/defender.go new file mode 100644 index 000000000..d9c2fe118 --- /dev/null +++ b/defender/defender.go @@ -0,0 +1,58 @@ +package defender + +import ( + "fmt" + "os" + "path/filepath" + "runtime" +) + +func excludePSFile() (string, error) { + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + return filepath.Join(home, ".gop/exclude.ps1"), nil +} + +func removePSFile() (string, error) { + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + return filepath.Join(home, ".gop/remove.ps1"), nil +} + +func Exclude() error { + if runtime.GOOS != "windows" { + return fmt.Errorf("not supported for %s", runtime.GOOS) + } + file, err := excludePSFile() + if err != nil { + return err + } + err = genGopDefenderExcludePSFile(file) + if err != nil { + return err + } + return runDefenderExcludePSFile(file) +} + +func Remove() error { + if runtime.GOOS != "windows" { + return fmt.Errorf("not supported for %s", runtime.GOOS) + } + exFile, err := excludePSFile() + if err != nil { + return err + } + file, err := removePSFile() + if err != nil { + return err + } + err = genGopDefenderRemovePSFile(exFile, file) + if err != nil { + return err + } + return runDefenderExcludePSFile(file) +} diff --git a/defender/gen.go b/defender/gen.go new file mode 100644 index 000000000..9ef1216ba --- /dev/null +++ b/defender/gen.go @@ -0,0 +1,176 @@ +package defender + +import ( + "bufio" + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "sync" +) + +func genGopDefenderExcludePSFile(psFile string) error { + cmd := exec.Command("powershell", "-nologo", "-noprofile") + stdin, err := cmd.StdinPipe() + if err != nil { + return err + } + resultMap := map[string]string{ + "gop env GOCACHE": "", + "gop env GOPROOT": "", + "gop env GOBIN": "", + "gop env GOENV": "", + "gop env GOPATH": ""} + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer stdin.Close() + for k := range resultMap { + fmt.Fprintln(stdin, k) + } + wg.Done() + }() + wg.Wait() + out, err := cmd.CombinedOutput() + if err != nil { + return err + } + buf := bytes.NewBuffer(out) + scanner := bufio.NewScanner(buf) + var key = "" + for scanner.Scan() { + lineText := scanner.Text() + index := strings.Index(lineText, "gop env") + if index > 0 { + key = lineText[index:] + } else { + if len(key) > 0 { + resultMap[key] = lineText + } + key = "" + } + } + f, err := os.Create(psFile) + if err != nil { + return err + } + defer f.Close() + for k, v := range resultMap { + if len(v) <= 0 || k == "gop env GOPROOT" { + continue + } + if k == "gop env GOCACHE" { + localDir := filepath.Dir(v) + goplsDir := filepath.Join(localDir, "/gopls") + if err := writeExcludeDirToFile(f, goplsDir); err != nil { + return err + } + } + if err := writeExcludeDirToFile(f, v); err != nil { + return err + } + } + if home, err := os.UserHomeDir(); err == nil { + if err := writeExcludeDirToFile(f, filepath.Join(home, ".gopls")); err != nil { + return err + } + if err := writeExcludeDirToFile(f, filepath.Join(home, ".gop")); err != nil { + return err + } + var exts = [11]string{ + "gop", + "go", + "yap", + "spx", + "rdx", + "gmx", + "gox", + "gsh", + "mod", + "sum", + } + for _, extStr := range exts { + if err := writeExcludeExtToFile(f, extStr); err != nil { + return err + } + } + } + return nil +} + +func genGopDefenderRemovePSFile(exFile string, file string) error { + if _, err := os.Stat(exFile); err != nil { + return err + } + cmd := exec.Command("powershell", "-nologo", "-noprofile") + stdin, err := cmd.StdinPipe() + if err != nil { + return err + } + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer stdin.Close() + cmdStr := fmt.Sprintf("powershell -Command \"(gc %s) -replace 'Add-MpPreference', 'Remove-MpPreference' | Out-File -encoding ASCII %s\"", exFile, file) + fmt.Fprintln(stdin, cmdStr) + wg.Done() + }() + wg.Wait() + _, err = cmd.CombinedOutput() + if err != nil { + return err + } + return nil +} + +func writeExcludeDirToFile(f *os.File, dir string) error { + _, err := f.WriteString(excludeDirString(dir)) + if err != nil { + return err + } + _, newLineError := f.WriteString("\r\n") + if newLineError != nil { + return newLineError + } + return nil +} + +func writeExcludeExtToFile(f *os.File, dir string) error { + _, err := f.WriteString(excludeExtString(dir)) + if err != nil { + return err + } + _, newLineError := f.WriteString("\r\n") + if newLineError != nil { + return newLineError + } + return nil +} + +func runDefenderExcludePSFile(file string) error { + _, err := os.Stat(file) + if err != nil { + return err + } + cmd := exec.Command("powershell", "-nologo", "-noprofile") + stdin, err := cmd.StdinPipe() + if err != nil { + return err + } + wg := sync.WaitGroup{} + wg.Add(1) + go func() { + defer stdin.Close() + startProcess := fmt.Sprintf("start-process -WindowStyle hidden powershell -verb runas -ArgumentList \"-file %s\"", file) + fmt.Fprintln(stdin, startProcess) + wg.Done() + }() + wg.Wait() + _, err = cmd.CombinedOutput() + if err != nil { + return err + } + return nil +}