diff --git a/gh-recon/deep.go b/gh-recon/deep.go index 16134f9..7c3e0f8 100644 --- a/gh-recon/deep.go +++ b/gh-recon/deep.go @@ -82,9 +82,10 @@ type DeepResult struct { Repository string Owner string Name string + Size int } -func (r Recon) Deep(username, excludeRepos string) (response []DeepResult) { +func (r Recon) Deep(username, excludeRepos string, refresh bool) (response []DeepResult) { excludeReposList := strings.Split(excludeRepos, ",") repos, resp, err := r.client.Repositories.ListByUser( r.ctx, @@ -107,6 +108,7 @@ func (r Recon) Deep(username, excludeRepos string) (response []DeepResult) { Repository: repo.GetCloneURL(), Owner: repo.GetOwner().GetLogin(), Name: repo.GetName(), + Size: repo.GetSize(), }) } } @@ -119,15 +121,43 @@ func (r Recon) Deep(username, excludeRepos string) (response []DeepResult) { } tmp_folder := "/tmp/ghrecon-" + username + + if folderExists(tmp_folder) { + if refresh { + r.PrintInfo("INFO", "Deleting existing folder "+tmp_folder) + err := os.RemoveAll(tmp_folder) + if err != nil { + r.PrintInfo("ERROR", "Failed to delete existing folder "+tmp_folder) + } + } + } + for _, repo := range response { if slices.Contains(excludeReposList, repo.Name) || slices.Contains(excludeReposList, repo.Owner+"/"+repo.Name) { r.PrintInfo("INFO", "Skipping repository", repo.Owner+"/"+repo.Name) continue } + + maxRepoSize := r.maxRepoSize * 1024 + + if repo.Size > maxRepoSize { + r.PrintInfo( + "INFO", + "Skipping repository "+repo.Owner+"/"+repo.Name+" due to size", fmt.Sprintf( + "%d", + repo.Size/1024, + )+"MB > "+fmt.Sprintf( + "%d", + maxRepoSize/1024, + )+"MB", + ) + continue + } r.PrintInfo( "Downloading", repo.Owner+"/"+repo.Name, + fmt.Sprintf("%d", repo.Size/1024)+"MB", ) destination := tmp_folder + "/" + repo.Owner + "/" + repo.Name diff --git a/gh-recon/main.go b/gh-recon/main.go index 07f619c..9baa85e 100644 --- a/gh-recon/main.go +++ b/gh-recon/main.go @@ -8,11 +8,12 @@ import ( ) type Recon struct { - client *github.Client - logger *log.Logger - ctx context.Context - silent bool - jsonFile string + client *github.Client + logger *log.Logger + ctx context.Context + silent bool + jsonFile string + maxRepoSize int } func NewRecon( @@ -21,12 +22,14 @@ func NewRecon( ctx context.Context, silent bool, jsonFile string, + maxRepoSize int, ) *Recon { return &Recon{ - client: client, - logger: logger, - ctx: ctx, - silent: silent, - jsonFile: jsonFile, + client: client, + logger: logger, + ctx: ctx, + silent: silent, + jsonFile: jsonFile, + maxRepoSize: maxRepoSize, } } diff --git a/main.go b/main.go index 48d0dcc..f9ee1b6 100644 --- a/main.go +++ b/main.go @@ -19,9 +19,17 @@ func main() { var silent bool var jsonFile string var excludeRepos string + var maxRepoSize int + var refresh bool flag.StringVarP(&username, "username", "u", "", "GitHub username to analyze") flag.StringVarP(&token, "token", "t", "", "GitHub personal access token (e.g. ghp_...)") flag.StringVarP(&fromEmail, "email", "e", "", "Search accounts by email address") + flag.IntVar( + &maxRepoSize, + "max-size", + 150, + "Limit the size of repositories to scan (in MB) (Only for deep scan)", + ) flag.BoolVarP( &onlyCommitsLeak, "only-commits", @@ -29,6 +37,13 @@ func main() { false, "Display only commits with author info", ) + flag.BoolVarP( + &refresh, + "refresh", + "r", + false, + "Refresh the cache (deep scan only)", + ) flag.BoolVarP( &deep, "deep", @@ -85,6 +100,7 @@ func main() { ctx, silent, jsonFile, + maxRepoSize, ) r.Header() @@ -130,7 +146,7 @@ func main() { } if deep { - results["Deep"] = r.Deep(username, excludeRepos) + results["Deep"] = r.Deep(username, excludeRepos, refresh) } r.WriteJson(results)