diff --git a/.replit b/.replit index 86703645..9b5e227a 100644 --- a/.replit +++ b/.replit @@ -1,6 +1,5 @@ -run = "make && echo \"UPM is built, can be found here: ./cmd/upm/upm\"" - -modules = ["go-1.20:v2-20230911-b5aa5df"] +run = "make upm && echo \"UPM is built, can be found here: ./cmd/upm/upm\"" +modules = ["bash", "bun-1.1", "go-1.21", "python-3.12"] [nix] -channel = "stable-23_05" +channel = "stable-24_05" diff --git a/internal/api/types.go b/internal/api/types.go index 4e18ce3d..b3e19d64 100644 --- a/internal/api/types.go +++ b/internal/api/types.go @@ -182,6 +182,10 @@ type LanguageBackend struct { // Check to see if we think we can run at all IsAvailable func() bool + // Check for signs that this backend has either been used or + // can be used to query + IsActive func() bool + // List of filename globs that match against files written in // this programming language, e.g. "*.py" for Python. These // should not include any slashes, because they may be matched diff --git a/internal/backends/nodejs/nodejs.go b/internal/backends/nodejs/nodejs.go index 9ae4a0e5..06b9f856 100644 --- a/internal/backends/nodejs/nodejs.go +++ b/internal/backends/nodejs/nodejs.go @@ -391,12 +391,20 @@ var tsxPathGlobs = []string{ "*.tsx", } +func commonIsActive(lockfile string) bool { + _, err := os.Stat(lockfile) + return !os.IsNotExist(err) +} + // NodejsYarnBackend is a UPM backend for Node.js that uses [Yarn](https://yarnpkg.com/). var NodejsYarnBackend = api.LanguageBackend{ Name: "nodejs-yarn", Specfile: "package.json", Lockfile: "yarn.lock", IsAvailable: yarnIsAvailable, + IsActive: func() bool { + return commonIsActive("yarn.lock") + }, FilenamePatterns: nodejsPatterns, Quirks: api.QuirksAddRemoveAlsoLocks | api.QuirksAddRemoveAlsoInstalls | @@ -481,6 +489,9 @@ var NodejsPNPMBackend = api.LanguageBackend{ Specfile: "package.json", Lockfile: "pnpm-lock.yaml", IsAvailable: pnpmIsAvailable, + IsActive: func() bool { + return commonIsActive("pnpm-lock.yaml") + }, FilenamePatterns: nodejsPatterns, Quirks: api.QuirksAddRemoveAlsoLocks | api.QuirksAddRemoveAlsoInstalls | @@ -581,6 +592,9 @@ var NodejsNPMBackend = api.LanguageBackend{ Specfile: "package.json", Lockfile: "package-lock.json", IsAvailable: npmIsAvailable, + IsActive: func() bool { + return commonIsActive("package-lock.json") + }, FilenamePatterns: nodejsPatterns, Quirks: api.QuirksAddRemoveAlsoLocks | api.QuirksAddRemoveAlsoInstalls | @@ -670,6 +684,9 @@ var BunBackend = api.LanguageBackend{ Specfile: "package.json", Lockfile: "bun.lockb", IsAvailable: bunIsAvailable, + IsActive: func() bool { + return commonIsActive("bun.lockb") + }, FilenamePatterns: nodejsPatterns, Quirks: api.QuirksAddRemoveAlsoLocks | api.QuirksAddRemoveAlsoInstalls | diff --git a/internal/backends/python/python.go b/internal/backends/python/python.go index 92be5938..278a2f91 100644 --- a/internal/backends/python/python.go +++ b/internal/backends/python/python.go @@ -301,6 +301,11 @@ func commonGuessPackageDir() string { return "" } +func commonIsActive(lockfile string) bool { + _, err := os.Stat(lockfile) + return !os.IsNotExist(err) +} + var pythonGuessRegexps = util.Regexps([]string{ // The (?:.|\\\n) subexpression allows us to // match match multiple lines if @@ -383,6 +388,9 @@ func makePythonPoetryBackend() api.LanguageBackend { _, err := exec.LookPath("poetry") return err == nil }, + IsActive: func() bool { + return commonIsActive("poetry.lock") + }, FilenamePatterns: []string{"*.py"}, Quirks: api.QuirksAddRemoveAlsoLocks | api.QuirksAddRemoveAlsoInstalls, @@ -754,6 +762,9 @@ func makePythonUvBackend() api.LanguageBackend { _, err := exec.LookPath("uv") return err == nil }, + IsActive: func() bool { + return commonIsActive("uv.lock") + }, Alias: "python-python3-uv", FilenamePatterns: []string{"*.py"}, Quirks: api.QuirksAddRemoveAlsoInstalls | api.QuirksAddRemoveAlsoLocks, diff --git a/internal/cli/cli.go b/internal/cli/cli.go index ac70b0d0..eeb19b22 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -96,9 +96,12 @@ func DoCLI() { Long: "Ask which language your project is autodetected as", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - runWhichLanguage(language) + runWhichLanguage(language, all) }, } + cmdWhichLanguage.Flags().BoolVarP( + &all, "all", "a", false, "List all packages for all detected languages", + ) rootCmd.AddCommand(cmdWhichLanguage) cmdListLanguages := &cobra.Command{ diff --git a/internal/cli/cmds.go b/internal/cli/cmds.go index 53d7b8c4..22e3e578 100644 --- a/internal/cli/cmds.go +++ b/internal/cli/cmds.go @@ -42,9 +42,29 @@ func (s *subroutineSilencer) restore() { } // runWhichLanguage implements 'upm which-language'. -func runWhichLanguage(language string) { - b := backends.GetBackend(context.Background(), language) - fmt.Println(b.Name) +func runWhichLanguage(language string, all bool) { + if !all { + b := backends.GetBackend(context.Background(), language) + fmt.Println(b.Name) + return + } + for _, bi := range backends.GetBackendNames() { + if !bi.Available { + continue + } + if language != "" && !strings.Contains(bi.Name, language) { + continue + } + + b := backends.GetBackend(context.Background(), bi.Name) + + // If we can't determine we are in use, don't report + if b.IsActive == nil || !b.IsActive() { + continue + } + + fmt.Println(b.Name) + } } // runListLanguages implements 'upm list-languages'.