From 56dfc6ce2d8cefe4cfe64903eaa990154484acaf Mon Sep 17 00:00:00 2001 From: Keshav Priyadarshi Date: Fri, 21 Jun 2024 23:31:38 +0530 Subject: [PATCH 1/2] Support lockfile generation for NuGet project Signed-off-by: Keshav Priyadarshi --- README.rst | 1 + cmd/nuget.go | 39 +++++++++++++++++++++++++++++++ cmd/root.go | 5 ++-- internal/utils.go | 58 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 cmd/nuget.go diff --git a/README.rst b/README.rst index 2d251e8..ae9a101 100644 --- a/README.rst +++ b/README.rst @@ -33,6 +33,7 @@ Supported Ecosystems - **swift**: https://www.swift.org/documentation/package-manager/ - **cocoapods**: https://cocoapods.org/ - **pypi**: https://pypi.org/ +- **nuget**: https://www.nuget.org/ Installation diff --git a/cmd/nuget.go b/cmd/nuget.go new file mode 100644 index 0000000..e4eb3e3 --- /dev/null +++ b/cmd/nuget.go @@ -0,0 +1,39 @@ +/* + +Copyright (c) nexB Inc. and others. All rights reserved. +ScanCode is a trademark of nexB Inc. +SPDX-License-Identifier: Apache-2.0 +See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +See https://github.com/nexB/dependency-inspector for support or download. +See https://aboutcode.org for more information about nexB OSS projects. + +*/ + +package cmd + +import ( + "github.com/nexB/dependency-inspector/internal" + "github.com/spf13/cobra" +) + +func nugetCmd() *cobra.Command { + forced := false + + nugetCmd := &cobra.Command{ + Use: "nuget [path]", + Short: "Generate lockfile for NuGet project", + Long: `Create lockfile for NuGet project if it doesn't exist in the specified [path]. +If no path is provided, the command defaults to the current directory.`, + Args: cobra.MaximumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + internal.CreateLockFileNuGet( + args, + forced, + ) + }, + } + + nugetCmd.Flags().BoolVarP(&forced, "force", "f", false, "Generate lockfile forcibly, ignoring existing lockfiles") + + return nugetCmd +} diff --git a/cmd/root.go b/cmd/root.go index 4537e53..f899083 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -25,9 +25,10 @@ var ecosystems = []func() *cobra.Command{ swiftCmd, cocoapodsCmd, pypiCmd, + nugetCmd, } -func NewRootCmd() *cobra.Command { +func rootCmd() *cobra.Command { rootCmd := &cobra.Command{ Use: "deplock", Short: "DepLock: Dependency Locker CLI", @@ -48,7 +49,7 @@ func initConfig(rootCmd *cobra.Command) { } func Execute() { - rootCmd := NewRootCmd() + rootCmd := rootCmd() if err := rootCmd.Execute(); err != nil { fmt.Fprintln(os.Stderr, "Error:", err) diff --git a/internal/utils.go b/internal/utils.go index 161c5e3..38b9bcb 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -19,15 +19,8 @@ import ( ) func CreateLockFile(lockFiles []string, cmdArgs []string, lockGenCmd []string, outputFileName string, forced bool) { - - path := "." - if len(cmdArgs) > 0 { - path = cmdArgs[0] - } - - absPath, err := filepath.Abs(path) - if err != nil { - fmt.Fprintln(os.Stderr, "Error: Failed to retrieve absolute path: ", err) + absPath := getAbsPath(cmdArgs) + if absPath == "" { return } @@ -66,8 +59,23 @@ func DoesFileExists(absPath string) bool { return false } +func getAbsPath(cmdArgs []string) string { + path := "." + if len(cmdArgs) > 0 { + path = cmdArgs[0] + } + + absPath, err := filepath.Abs(path) + if err != nil { + fmt.Fprintln(os.Stderr, "Error: Failed to retrieve absolute path: ", err) + return "" + } + + return absPath +} + func genLock(lockGenCmd []string, absPath string, outputFileName string) { - fmt.Printf("Generating lockfile using '%s'\n", lockGenCmd) + fmt.Printf("Generating lockfile at '%s' using '%s'\n", absPath, lockGenCmd) // #nosec G204 command := exec.Command(lockGenCmd[0], lockGenCmd[1:]...) @@ -96,3 +104,33 @@ func genLock(lockGenCmd []string, absPath string, outputFileName string) { fmt.Println("Lock file generated successfully.") } + +func CreateLockFileNuGet(cmdArgs []string, force bool) { + nuGetLockFileName := "packages.lock.json" + nuGetLockFileGenCmd := []string{"dotnet", "restore", "--use-lock-file"} + + project_path := getAbsPath(cmdArgs) + if project_path == "" { + return + } + + csproj_pattern := filepath.Join(project_path, "*", "*.csproj") + fmt.Println(csproj_pattern) + + csproj_files, err := filepath.Glob(csproj_pattern) + if err != nil { + fmt.Fprintln(os.Stderr, "Error: Path does not contain a NuGet project: ", err) + return + } + + // Generate lockfile for all NuGet projects + for _, file := range csproj_files { + dir := filepath.Dir(file) + lockFile := filepath.Join(dir, nuGetLockFileName) + if !DoesFileExists(lockFile) || force { + genLock(nuGetLockFileGenCmd, dir, "") + } + + } + +} From 9611efc77e06b8962bebc87388bd4c54af2f8642 Mon Sep 17 00:00:00 2001 From: Keshav Priyadarshi Date: Sat, 22 Jun 2024 01:02:50 +0530 Subject: [PATCH 2/2] Generate lockfile for all NuGet packages Signed-off-by: Keshav Priyadarshi --- go.mod | 5 ++++- go.sum | 2 ++ internal/utils.go | 19 ++++++++++++------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 5b316d8..386643a 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module github.com/nexB/dependency-inspector go 1.22.3 -require github.com/spf13/cobra v1.8.0 +require ( + github.com/bmatcuk/doublestar/v4 v4.6.1 + github.com/spf13/cobra v1.8.0 +) require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index d0e8c2c..0ed62cc 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= +github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= diff --git a/internal/utils.go b/internal/utils.go index 38b9bcb..0c60467 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -16,6 +16,8 @@ import ( "os" "os/exec" "path/filepath" + + "github.com/bmatcuk/doublestar/v4" ) func CreateLockFile(lockFiles []string, cmdArgs []string, lockGenCmd []string, outputFileName string, forced bool) { @@ -25,6 +27,7 @@ func CreateLockFile(lockFiles []string, cmdArgs []string, lockGenCmd []string, o } if !forced { + // If any lockfile is present already then skip lockfile generation. for _, lockFile := range lockFiles { lockFileAbsPath := filepath.Join(absPath, lockFile) @@ -114,20 +117,22 @@ func CreateLockFileNuGet(cmdArgs []string, force bool) { return } - csproj_pattern := filepath.Join(project_path, "*", "*.csproj") - fmt.Println(csproj_pattern) + fs := os.DirFS(project_path) + csproj_pattern := "**/*.csproj" - csproj_files, err := filepath.Glob(csproj_pattern) - if err != nil { - fmt.Fprintln(os.Stderr, "Error: Path does not contain a NuGet project: ", err) + csproj_files, _ := doublestar.Glob(fs, csproj_pattern) + if len(csproj_files) == 0 { + fmt.Fprintln(os.Stderr, "Error: Path does not contain a NuGet project") return } // Generate lockfile for all NuGet projects for _, file := range csproj_files { - dir := filepath.Dir(file) + fullPath := filepath.Join(project_path, file) + dir := filepath.Dir(fullPath) + lockFile := filepath.Join(dir, nuGetLockFileName) - if !DoesFileExists(lockFile) || force { + if force || !DoesFileExists(lockFile) { genLock(nuGetLockFileGenCmd, dir, "") }