@@ -3,6 +3,7 @@ package main
33import (
44 "context"
55 "encoding/json"
6+ "flag"
67 "fmt"
78 "os"
89 "os/exec"
@@ -13,23 +14,27 @@ import (
1314)
1415
1516func main () {
16- response := processRepository ()
17+ noLarge := flag .Bool ("no-large" , false , "Skip files larger than 100MB to avoid OOM on large repos" )
18+ flag .Parse ()
19+
20+ response := processRepository (* noLarge )
1721 outputJSON (response )
1822
1923 // Always exit with code 0 - status details are in JSON response
2024}
2125
2226// processRepository handles the main logic and returns a StandardResponse
23- func processRepository () StandardResponse {
27+ func processRepository (noLarge bool ) StandardResponse {
2428 ctx := context .Background ()
2529
26- // Get target path from command line argument
30+ // Get target path from remaining non-flag arguments
31+ args := flag .Args ()
2732 var targetPath string
28- if len (os . Args ) > 1 {
29- targetPath = os . Args [ 1 ]
33+ if len (args ) > 0 {
34+ targetPath = args [ 0 ]
3035 } else {
3136 errorCode := ErrorCodeInvalidArguments
32- errorMessage := fmt .Sprintf ("Usage: %s <target-path>" , os .Args [0 ])
37+ errorMessage := fmt .Sprintf ("Usage: %s [--no-large] <target-path>" , os .Args [0 ])
3338 return StandardResponse {
3439 Status : StatusFailure ,
3540 ErrorCode : & errorCode ,
@@ -51,10 +56,10 @@ func processRepository() StandardResponse {
5156 // Process single repository (the target path argument)
5257 repoDir := config .TargetPath
5358
54- insightsDb , err := NewInsightsDB (ctx , config .InsightsDatabase )
55- if err != nil {
59+ insightsDb , dbErr := NewInsightsDB (ctx , config .InsightsDatabase )
60+ if dbErr != nil {
5661 errorCode := ErrorCodeDatabaseConnection
57- errorMessage := fmt .Sprintf ("Error connecting to insights database: %v" , err )
62+ errorMessage := fmt .Sprintf ("Error connecting to insights database: %v" , dbErr )
5863 return StandardResponse {
5964 Status : StatusFailure ,
6065 ErrorCode : & errorCode ,
@@ -76,7 +81,7 @@ func processRepository() StandardResponse {
7681 }
7782
7883 // Process the repository with SCC
79- report , err := getSCCReport (config .SCCPath , repoDir )
84+ report , err := getSCCReport (config .SCCPath , repoDir , noLarge )
8085 if err != nil {
8186 errorCode := getErrorCodeFromSCCError (err )
8287 errorMessage := fmt .Sprintf ("Error processing repository '%s': %v" , repoDir , err )
@@ -120,10 +125,10 @@ func processRepository() StandardResponse {
120125
121126
122127// getSCCReport analyzes a directory with scc and returns a report containing the estimated cost and language statistics.
123- func getSCCReport (sccPath , dirPath string ) (SCCReport , error ) {
124- cost , err := getCost (sccPath , dirPath )
128+ func getSCCReport (sccPath , dirPath string , noLarge bool ) (SCCReport , error ) {
129+ cost , err := getCost (sccPath , dirPath , noLarge )
125130 if err != nil {
126- return SCCReport {}, fmt .Errorf ("error getting SCC report for '%s': %v\" " , err )
131+ return SCCReport {}, fmt .Errorf ("error getting SCC report for '%s': %v" , dirPath , err )
127132 }
128133
129134 // Skip saving to database if cost is 0 - do we want to do this?
@@ -133,7 +138,7 @@ func getSCCReport(sccPath, dirPath string) (SCCReport, error) {
133138
134139 projectPath := filepath .Base (dirPath )
135140
136- langStats , err := getLanguageStats (sccPath , dirPath )
141+ langStats , err := getLanguageStats (sccPath , dirPath , noLarge )
137142 if err != nil {
138143 return SCCReport {}, fmt .Errorf ("error getting language stats for '%s': %v" , dirPath , err )
139144 }
@@ -177,8 +182,8 @@ func getGitRepositoryURL(dirPath string) (string, error) {
177182}
178183
179184// getCost runs the scc command and parses the output to get the estimated cost.
180- func getCost (sccPathPath , repoPath string ) (float64 , error ) {
181- output , err := runSCC (sccPathPath , "--format=short" , repoPath )
185+ func getCost (sccPathPath , repoPath string , noLarge bool ) (float64 , error ) {
186+ output , err := runSCC (sccPathPath , noLarge , "--format=short" , repoPath )
182187 if err != nil {
183188 return 0 , fmt .Errorf ("failed to run scc command: %w" , err )
184189 }
@@ -192,8 +197,8 @@ func getCost(sccPathPath, repoPath string) (float64, error) {
192197}
193198
194199// getLanguageStats runs the scc command and parses the output to get language statistics.
195- func getLanguageStats (sccPathPath , repoPath string ) ([]LanguageStats , error ) {
196- output , err := runSCC (sccPathPath , "--format=json" , repoPath )
200+ func getLanguageStats (sccPathPath , repoPath string , noLarge bool ) ([]LanguageStats , error ) {
201+ output , err := runSCC (sccPathPath , noLarge , "--format=json" , repoPath )
197202 if err != nil {
198203 return nil , fmt .Errorf ("failed to run scc command: %w" , err )
199204 }
@@ -207,8 +212,14 @@ func getLanguageStats(sccPathPath, repoPath string) ([]LanguageStats, error) {
207212}
208213
209214// runSCC executes the scc command with the given arguments and returns the output.
210- func runSCC (sccPathPath string , args ... string ) (string , error ) {
211- cmd := exec .Command (sccPathPath , args ... )
215+ // When noLarge is true, files larger than 100MB are skipped to avoid OOM on large repos.
216+ func runSCC (sccPathPath string , noLarge bool , args ... string ) (string , error ) {
217+ var cmdArgs []string
218+ if noLarge {
219+ cmdArgs = append (cmdArgs , "--no-large" , "--large-byte-count" , "100000000" )
220+ }
221+ cmdArgs = append (cmdArgs , args ... )
222+ cmd := exec .Command (sccPathPath , cmdArgs ... )
212223 output , err := cmd .Output ()
213224 if err != nil {
214225 if exitErr , ok := err .(* exec.ExitError ); ok {
0 commit comments