77 "codacy/cli-v2/utils"
88 "codacy/cli-v2/utils/logger"
99 "fmt"
10+ "io"
1011 "log"
1112 "os"
1213 "os/exec"
@@ -297,29 +298,43 @@ func installDownloadBasedTool(toolInfo *plugins.ToolInfo) error {
297298 return fmt .Errorf ("failed to create installation directory: %w" , err )
298299 }
299300
300- // Extract based on file extension
301- logger .Debug ("Extracting tool" , logrus.Fields {
302- "tool" : toolInfo .Name ,
303- "version" : toolInfo .Version ,
304- "fileName" : fileName ,
305- "extractDirectory" : toolInfo .InstallDir ,
306- })
301+ isArchive := strings .HasSuffix (fileName , ".zip" ) || strings .HasSuffix (fileName , ".tar.gz" ) || strings .HasSuffix (fileName , ".tgz" )
307302
308- if strings .HasSuffix (fileName , ".zip" ) {
309- err = utils .ExtractZip (file .Name (), toolInfo .InstallDir )
310- } else {
311- err = utils .ExtractTarGz (file , toolInfo .InstallDir )
312- }
303+ if isArchive {
304+ // Extract based on file extension
305+ logger .Debug ("Extracting tool" , logrus.Fields {
306+ "tool" : toolInfo .Name ,
307+ "version" : toolInfo .Version ,
308+ "fileName" : fileName ,
309+ "extractDirectory" : toolInfo .InstallDir ,
310+ })
313311
314- if err != nil {
315- return fmt .Errorf ("failed to extract tool: %w" , err )
316- }
312+ if strings .HasSuffix (fileName , ".zip" ) {
313+ err = utils .ExtractZip (file .Name (), toolInfo .InstallDir )
314+ } else {
315+ err = utils .ExtractTarGz (file , toolInfo .InstallDir )
316+ }
317+
318+ if err != nil {
319+ return fmt .Errorf ("failed to extract tool: %w" , err )
320+ }
317321
318- // Make sure all binaries are executable
319- for _ , binaryPath := range toolInfo .Binaries {
320- err = os .Chmod (filepath .Join (toolInfo .InstallDir , filepath .Base (binaryPath )), constants .DefaultDirPerms )
321- if err != nil && ! os .IsNotExist (err ) {
322- return fmt .Errorf ("failed to make binary executable: %w" , err )
322+ // Make sure all binaries are executable
323+ for _ , binaryPath := range toolInfo .Binaries {
324+ err = os .Chmod (filepath .Join (toolInfo .InstallDir , filepath .Base (binaryPath )), constants .DefaultDirPerms )
325+ if err != nil && ! os .IsNotExist (err ) {
326+ return fmt .Errorf ("failed to make binary executable: %w" , err )
327+ }
328+ }
329+ } else {
330+ // Bare binary — copy directly to the binary destination path
331+ logger .Debug ("Installing bare binary" , logrus.Fields {
332+ "tool" : toolInfo .Name ,
333+ "version" : toolInfo .Version ,
334+ "downloadPath" : downloadPath ,
335+ })
336+ if err = installBareBinary (downloadPath , toolInfo ); err != nil {
337+ return fmt .Errorf ("failed to install binary: %w" , err )
323338 }
324339 }
325340
@@ -330,6 +345,44 @@ func installDownloadBasedTool(toolInfo *plugins.ToolInfo) error {
330345 return nil
331346}
332347
348+ // installBareBinary copies a downloaded bare binary to its destination path and makes it executable.
349+ func installBareBinary (downloadPath string , toolInfo * plugins.ToolInfo ) error {
350+ var destPath string
351+ for _ , p := range toolInfo .Binaries {
352+ destPath = p
353+ break
354+ }
355+ if destPath == "" {
356+ return fmt .Errorf ("no binary destination defined for tool %s" , toolInfo .Name )
357+ }
358+
359+ if err := os .MkdirAll (filepath .Dir (destPath ), constants .DefaultDirPerms ); err != nil {
360+ return fmt .Errorf ("failed to create binary directory: %w" , err )
361+ }
362+
363+ src , err := os .Open (downloadPath )
364+ if err != nil {
365+ return fmt .Errorf ("failed to open downloaded binary: %w" , err )
366+ }
367+ defer src .Close ()
368+
369+ dst , err := os .Create (destPath )
370+ if err != nil {
371+ return fmt .Errorf ("failed to create binary file: %w" , err )
372+ }
373+ defer dst .Close ()
374+
375+ if _ , err = io .Copy (dst , src ); err != nil {
376+ return fmt .Errorf ("failed to copy binary: %w" , err )
377+ }
378+
379+ if err = os .Chmod (destPath , constants .DefaultDirPerms ); err != nil {
380+ return fmt .Errorf ("failed to make binary executable: %w" , err )
381+ }
382+
383+ return nil
384+ }
385+
333386func installPythonTool (name string , toolInfo * plugins.ToolInfo ) error {
334387 logger .Debug ("Starting Python tool installation" , logrus.Fields {
335388 "tool" : toolInfo .Name ,
0 commit comments