.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / internal / lsp / lsprpc / autostart_posix.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/lsprpc/autostart_posix.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/lsprpc/autostart_posix.go
new file mode 100644 (file)
index 0000000..9ad3f1d
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package lsprpc
+
+import (
+       "crypto/sha256"
+       "errors"
+       "fmt"
+       exec "golang.org/x/sys/execabs"
+       "log"
+       "os"
+       "os/user"
+       "path/filepath"
+       "strconv"
+       "syscall"
+
+       "golang.org/x/xerrors"
+)
+
+func init() {
+       startRemote = startRemotePosix
+       autoNetworkAddress = autoNetworkAddressPosix
+       verifyRemoteOwnership = verifyRemoteOwnershipPosix
+}
+
+func startRemotePosix(goplsPath string, args ...string) error {
+       cmd := exec.Command(goplsPath, args...)
+       cmd.SysProcAttr = &syscall.SysProcAttr{
+               Setsid: true,
+       }
+       if err := cmd.Start(); err != nil {
+               return xerrors.Errorf("starting remote gopls: %w", err)
+       }
+       return nil
+}
+
+// autoNetworkAddress resolves an id on the 'auto' pseduo-network to a
+// real network and address. On unix, this uses unix domain sockets.
+func autoNetworkAddressPosix(goplsPath, id string) (network string, address string) {
+       // Especially when doing local development or testing, it's important that
+       // the remote gopls instance we connect to is running the same binary as our
+       // forwarder. So we encode a short hash of the binary path into the daemon
+       // socket name. If possible, we also include the buildid in this hash, to
+       // account for long-running processes where the binary has been subsequently
+       // rebuilt.
+       h := sha256.New()
+       cmd := exec.Command("go", "tool", "buildid", goplsPath)
+       cmd.Stdout = h
+       var pathHash []byte
+       if err := cmd.Run(); err == nil {
+               pathHash = h.Sum(nil)
+       } else {
+               log.Printf("error getting current buildid: %v", err)
+               sum := sha256.Sum256([]byte(goplsPath))
+               pathHash = sum[:]
+       }
+       shortHash := fmt.Sprintf("%x", pathHash)[:6]
+       user := os.Getenv("USER")
+       if user == "" {
+               user = "shared"
+       }
+       basename := filepath.Base(goplsPath)
+       idComponent := ""
+       if id != "" {
+               idComponent = "-" + id
+       }
+       runtimeDir := os.TempDir()
+       if xdg := os.Getenv("XDG_RUNTIME_DIR"); xdg != "" {
+               runtimeDir = xdg
+       }
+       return "unix", filepath.Join(runtimeDir, fmt.Sprintf("%s-%s-daemon.%s%s", basename, shortHash, user, idComponent))
+}
+
+func verifyRemoteOwnershipPosix(network, address string) (bool, error) {
+       if network != "unix" {
+               return true, nil
+       }
+       fi, err := os.Stat(address)
+       if err != nil {
+               if os.IsNotExist(err) {
+                       return true, nil
+               }
+               return false, xerrors.Errorf("checking socket owner: %w", err)
+       }
+       stat, ok := fi.Sys().(*syscall.Stat_t)
+       if !ok {
+               return false, errors.New("fi.Sys() is not a Stat_t")
+       }
+       user, err := user.Current()
+       if err != nil {
+               return false, xerrors.Errorf("checking current user: %w", err)
+       }
+       uid, err := strconv.ParseUint(user.Uid, 10, 32)
+       if err != nil {
+               return false, xerrors.Errorf("parsing current UID: %w", err)
+       }
+       return stat.Uid == uint32(uid), nil
+}