55 "encoding/json"
66 "fmt"
77 "github.com/jfrog/gofrog/datastructures"
8+ version2 "github.com/jfrog/gofrog/version"
89 "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
910 "github.com/jfrog/jfrog-cli-security/utils"
1011 "github.com/jfrog/jfrog-cli-security/utils/formats/sarifutils"
@@ -22,7 +23,12 @@ import (
2223const (
2324 // VersionForMainModule - We don't have information in swift on the current package, or main module, we only have information on its
2425 // dependencies.
25- VersionForMainModule = "0.0.0"
26+ VersionForMainModule = "0.0.0"
27+ VERSION_SYNTAX_TYPE_INDEX = 1
28+ EXACT_VERSION_INDEX = 2
29+ FROM_VERSION_INDEX = 3
30+ START_RANGE_INDEX = 4
31+ END_RANGE_INDEX = 5
2632)
2733
2834type Dependencies struct {
@@ -36,7 +42,7 @@ func GetTechDependencyLocation(directDependencyName, directDependencyVersion str
3642 for _ , descriptorPath := range descriptorPaths {
3743 path .Clean (descriptorPath )
3844 if ! strings .HasSuffix (descriptorPath , "Package.swift" ) {
39- log .Logger . Warn ("Cannot support other files besides Package.swift: %s" , descriptorPath )
45+ log .Warn ("Cannot support other files besides Package.swift: %s" , descriptorPath )
4046 continue
4147 }
4248 data , err := os .ReadFile (descriptorPath )
@@ -90,42 +96,81 @@ func parseSwiftLine(line, directDependencyName, directDependencyVersion, descrip
9096 return foundDependency , tempIndex , startLine , startCol
9197}
9298
99+ func handleNonRangeMatches (match , name , fixVersion string , index int , submatches []string ) string {
100+ log .Debug ("Fixing dependency" , name , "from version" , submatches [index ], "to" , fixVersion )
101+ return strings .Replace (match , submatches [index ], fixVersion , 1 )
102+ }
103+
104+ func handleRangeMatches (match , name , fixVersion string , submatches []string ) string {
105+ startVersion := submatches [START_RANGE_INDEX ]
106+ endVersion := submatches [END_RANGE_INDEX ]
107+ if version2 .NewVersion (fixVersion ).Compare (startVersion ) < 1 && version2 .NewVersion (fixVersion ).Compare (endVersion ) == 1 {
108+ // Replace the start of the range with `fixVersion`
109+ log .Debug ("Fixing dependency" , name , "from start version" , startVersion , "to" , fixVersion )
110+ return strings .Replace (match , startVersion , fixVersion , 1 )
111+ }
112+ return match
113+ }
114+
115+ func updateDependency (content , name , version , fixVersion string ) string {
116+ urlPattern := `(?:https://|http://|sso://)?` + regexp .QuoteMeta (strings .TrimSuffix (name , ".git" )) + `(?:\.git)?`
117+ pattern := `\.package\(url:\s*"` + urlPattern + `",\s*(exact:\s*"(` + version + `)"|from:\s*"(` + version + `)"|"([\d\.]+)"\.\.\s*<?\s*"([\d\.]+)")\)`
118+ re := regexp .MustCompile (pattern )
119+ result := re .ReplaceAllStringFunc (content , func (match string ) string {
120+ submatches := re .FindStringSubmatch (match )
121+ if len (submatches ) == 0 {
122+ return match
123+ }
124+
125+ // Handle exact match
126+ if len (submatches ) > VERSION_SYNTAX_TYPE_INDEX && strings .Contains (submatches [VERSION_SYNTAX_TYPE_INDEX ], "exact" ) {
127+ return handleNonRangeMatches (match , name , fixVersion , EXACT_VERSION_INDEX , submatches )
128+ }
129+
130+ // Handle from match
131+ if len (submatches ) > VERSION_SYNTAX_TYPE_INDEX && strings .Contains (submatches [VERSION_SYNTAX_TYPE_INDEX ], "from" ) {
132+ return handleNonRangeMatches (match , name , fixVersion , FROM_VERSION_INDEX , submatches )
133+ }
134+
135+ // Handle range case
136+ if len (submatches ) > 5 && submatches [START_RANGE_INDEX ] != "" && submatches [END_RANGE_INDEX ] != "" {
137+ return handleRangeMatches (match , name , fixVersion , submatches )
138+ }
139+ return match
140+ })
141+ return result
142+ }
143+
93144func FixTechDependency (dependencyName , dependencyVersion , fixVersion string , descriptorPaths ... string ) error {
94145 for _ , descriptorPath := range descriptorPaths {
95146 path .Clean (descriptorPath )
96147 if ! strings .HasSuffix (descriptorPath , "Package.swift" ) {
97- log .Logger . Warn ("Cannot support other files besides Package.swift: %s " , descriptorPath )
148+ log .Warn ("Cannot support other files besides Package.swift: " , descriptorPath )
98149 continue
99150 }
100151 data , err := os .ReadFile (descriptorPath )
101- var newLines []string
102152 if err != nil {
153+ log .Warn ("Error reading file: " , descriptorPath , err )
103154 continue
104155 }
105- lines := strings .Split (string (data ), "\n " )
106- foundDependency := false
107- var tempIndex int
108- for index , line := range lines {
109- if strings .Contains (line , dependencyName ) {
110- foundDependency = true
111- tempIndex = index
156+ updatedContent := updateDependency (string (data ), dependencyName , dependencyVersion , fixVersion )
157+ if strings .Compare (string (data ), updatedContent ) != 0 {
158+ if err = os .WriteFile (descriptorPath , []byte (updatedContent ), 0644 ); err != nil {
159+ return fmt .Errorf ("failed to write file: %v" , err )
112160 }
113- // This means we are in a new dependency (we cannot find dependency name and version together)
114- //nolint:gocritic
115- if index > tempIndex && foundDependency && strings .Contains (line , ".package" ) {
116- foundDependency = false
117- } else if foundDependency && strings .Contains (line , dependencyVersion ) {
118- newLine := strings .Replace (line , dependencyVersion , fixVersion , 1 )
119- newLines = append (newLines , newLine )
120- foundDependency = false
121- } else {
122- newLines = append (newLines , line )
161+ currentDir , err := coreutils .GetWorkingDirectory ()
162+ if err != nil {
163+ return fmt .Errorf ("could not run swift build due to %s" , err )
123164 }
124- }
125- output := strings .Join (newLines , "\n " )
126- err = os .WriteFile (descriptorPath , []byte (output ), 0644 )
127- if err != nil {
128- return fmt .Errorf ("failed to write file: %v" , err )
165+ _ , exePath , err := getSwiftVersionAndExecPath ()
166+ if err != nil {
167+ return fmt .Errorf ("could not run swift build due to %s" , err )
168+ }
169+ if _ , err = runSwiftCmd (exePath , currentDir , []string {"build" }); err != nil {
170+ return fmt .Errorf ("could not run swift build due to %s" , err )
171+ }
172+ } else {
173+ log .Debug ("No fixes were done in file" , descriptorPath )
129174 }
130175 }
131176 return nil
0 commit comments