1414 limitations under the License.
1515*/
1616
17- package utils
17+ package config
1818
1919import (
2020 "encoding/json"
2121 "errors"
22+ "io/fs"
2223 "os"
2324 "path/filepath"
2425 "regexp"
26+ "slices"
2527 "strings"
2628)
2729
@@ -42,9 +44,9 @@ type Config struct {
4244var multiLineCommentsRegex = regexp .MustCompile (`(?s)\s*/\*.*?\*/` )
4345var singleLineCommentsRegex = regexp .MustCompile (`\s*//.*\s*` )
4446
45- // SaveConfig saves the config to the given file.
46- func SaveConfig ( config Config , file * os.File ) error {
47- bytes , err := json .MarshalIndent (config , "" , " " )
47+ // Saves the config to the given file.
48+ func ( c * Config ) Save ( file * os.File ) error {
49+ bytes , err := json .MarshalIndent (c , "" , " " )
4850 if err != nil {
4951 return err
5052 }
@@ -66,7 +68,8 @@ func LoadConfig(path string) (Config, error) {
6668 }
6769
6870 // Strip the comments and load the JSON.
69- sourceJson := StripComments (sourceJsonc )
71+ sourceJson := multiLineCommentsRegex .ReplaceAll (sourceJsonc , []byte {})
72+ sourceJson = singleLineCommentsRegex .ReplaceAll (sourceJson , []byte {})
7073 err = json .Unmarshal (sourceJson , & config )
7174 if err != nil {
7275 return config , err
@@ -83,12 +86,6 @@ func LoadConfig(path string) (Config, error) {
8386 return config , nil
8487}
8588
86- // StripComments removes comments from the given source.
87- func StripComments (src []byte ) []byte {
88- src = multiLineCommentsRegex .ReplaceAll (src , []byte {})
89- return singleLineCommentsRegex .ReplaceAll (src , []byte {})
90- }
91-
9289// Match returns true if the path matches any of the patterns.
9390func Match (patterns []string , path string ) bool {
9491 filename := filepath .Base (path )
@@ -104,12 +101,12 @@ func Match(patterns []string, path string) bool {
104101}
105102
106103// Matches returns true if the path matches the config.
107- func (c Config ) Matches (path string ) bool {
104+ func (c * Config ) Matches (path string ) bool {
108105 return Match (c .Match , path ) && ! Match (c .Ignore , path )
109106}
110107
111108// IsPackageDir returns true if the path is a package directory.
112- func (c Config ) IsPackageDir (dir string ) bool {
109+ func (c * Config ) IsPackageDir (dir string ) bool {
113110 for _ , filename := range c .PackageFile {
114111 packageFile := filepath .Join (dir , filename )
115112 if fileExists (packageFile ) {
@@ -120,18 +117,70 @@ func (c Config) IsPackageDir(dir string) bool {
120117}
121118
122119// FindPackage returns the package name for the given path.
123- func (c Config ) FindPackage (path string ) string {
120+ func (c * Config ) FindPackage (path string ) string {
124121 dir := filepath .Dir (path )
125122 if dir == "." || c .IsPackageDir (dir ) {
126123 return dir
127124 }
128125 return c .FindPackage (dir )
129126}
130127
131- // fileExists returns true if the file exists.
132- func fileExists (path string ) bool {
133- if _ , err := os .Stat (path ); errors .Is (err , os .ErrNotExist ) {
134- return false
128+ // FindAllPackages finds all the packages in the given root directory.
129+ func (c * Config ) FindAllPackages (root string ) ([]string , error ) {
130+ var packages []string
131+ err := fs .WalkDir (os .DirFS (root ), "." ,
132+ func (path string , d os.DirEntry , err error ) error {
133+ if err != nil {
134+ return err
135+ }
136+ if path == "." {
137+ return nil
138+ }
139+ if slices .Contains (c .ExcludePackages , path ) {
140+ return nil
141+ }
142+ if d .IsDir () && c .Matches (path ) && c .IsPackageDir (path ) {
143+ packages = append (packages , path )
144+ return nil
145+ }
146+ return nil
147+ })
148+ if err != nil {
149+ return []string {}, err
150+ }
151+ return packages , nil
152+ }
153+
154+ // Affected returns the packages that have been affected from diffs.
155+ func (c * Config ) Affected (diffs []string ) ([]string , error ) {
156+ changed := c .Changed (diffs )
157+ if slices .Contains (changed , "." ) {
158+ return c .FindAllPackages ("." )
159+ }
160+ return changed , nil
161+ }
162+
163+ // Changed returns the packages that have changed.
164+ func (c * Config ) Changed (diffs []string ) []string {
165+ changedUnique := make (map [string ]bool )
166+ for _ , diff := range diffs {
167+ if ! c .Matches (diff ) {
168+ continue
169+ }
170+ pkg := c .FindPackage (diff )
171+ if slices .Contains (c .ExcludePackages , pkg ) {
172+ continue
173+ }
174+ changedUnique [pkg ] = true
175+ }
176+
177+ if len (changedUnique ) == 0 {
178+ return []string {"." }
179+ }
180+
181+ changed := make ([]string , 0 , len (changedUnique ))
182+ for pkg := range changedUnique {
183+ changed = append (changed , pkg )
135184 }
136- return true
185+ return changed
137186}
0 commit comments