diff --git a/which/which.go b/which/which.go new file mode 100644 index 0000000..4190ea4 --- /dev/null +++ b/which/which.go @@ -0,0 +1,54 @@ +package which + +import ( + "errors" + "os" + "path" + "strings" +) + +// Common named errors to match in programs using this library +var ( + ErrBinaryNotFound = errors.New("Requested binary was not found") + ErrNoSearchSpecified = errors.New("You need to specify a binary to search") +) + +// FindInPath searches the specified binary in directories listed in $PATH and returns first match +func FindInPath(binary string) (string, error) { + pathEnv := os.Getenv("PATH") + if len(pathEnv) == 0 { + return "", errors.New("Found empty $PATH, not able to search $PATH") + } + + for _, part := range strings.Split(pathEnv, ":") { + if len(part) == 0 { + continue + } + + if found, err := FindInDirectory(binary, part); err != nil { + return "", err + } else if found { + return path.Join(part, binary), nil + } + } + + return "", ErrBinaryNotFound +} + +// FindInDirectory checks whether the specified file is present in the directory +func FindInDirectory(binary, directory string) (bool, error) { + if len(binary) == 0 { + return false, ErrNoSearchSpecified + } + + _, err := os.Stat(path.Join(directory, binary)) + + switch { + case err == nil: + return true, nil + case os.IsNotExist(err): + return false, nil + default: + return false, err + } +} diff --git a/which/which_suite_test.go b/which/which_suite_test.go new file mode 100644 index 0000000..90a20b5 --- /dev/null +++ b/which/which_suite_test.go @@ -0,0 +1,13 @@ +package which_test + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "testing" +) + +func TestWhich(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Which Suite") +} diff --git a/which/which_test.go b/which/which_test.go new file mode 100644 index 0000000..d9a30c2 --- /dev/null +++ b/which/which_test.go @@ -0,0 +1,63 @@ +package which_test + +import ( + . "github.com/Luzifer/go_helpers/which" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Which", func() { + var ( + result string + err error + found bool + ) + + Context("With a file available on linux systems", func() { + BeforeEach(func() { + found, err = FindInDirectory("bash", "/bin") + }) + + It("should not have errored", func() { + Expect(err).NotTo(HaveOccurred()) + }) + It("should have found the binary at /bin/bash", func() { + Expect(found).To(BeTrue()) + }) + }) + + Context("Searching bash on the system", func() { + BeforeEach(func() { + result, err = FindInPath("bash") + }) + + It("should not have errored", func() { + Expect(err).NotTo(HaveOccurred()) + }) + It("should have a result", func() { + Expect(len(result)).NotTo(Equal(0)) + }) + }) + + Context("Searching a non existent file", func() { + BeforeEach(func() { + result, err = FindInPath("dfqoiwurgtqi3uegrds") + }) + + It("should have errored", func() { + Expect(err).To(Equal(ErrBinaryNotFound)) + }) + }) + + Context("Searching an empty file", func() { + BeforeEach(func() { + result, err = FindInPath("") + }) + + It("should have errored", func() { + Expect(err).To(Equal(ErrNoSearchSpecified)) + }) + }) + +})