async Task <IEnumerable <SearchResult> > SearchRepoAsync(GitHubRepo repo, bool handleRenamedRepos = true)
        {
            object operation = null;

            try
            {
                List <SearchResult> ret = new List <SearchResult>();

                if (_storage.IsNotFound(repo.Owner, repo.Name))
                {
                    _logger.Verbose("{Repo} previously not found, skipping", repo.Owner + "/" + repo.Name);
                    return(Enumerable.Empty <SearchResult>());
                }

                if (_storage.HasRepoResults(repo.Owner, repo.Name))
                {
                    _logger.Verbose("{Repo} already downloaded", repo.Owner + "/" + repo.Name);
                    ret = _storage.GetRepoResults(repo.Owner, repo.Name).ToList();
                }
                else
                {
                    var request = new SearchCodeRequest()
                    {
                        FileName = "project.json",
                    };
                    request.Repos.Add(repo.Owner, repo.Name);

                    int totalResultsReturned = 0;

                    while (true)
                    {
                        if (_cancelToken.IsCancellationRequested)
                        {
                            return(Enumerable.Empty <SearchResult>());
                        }

                        operation = new { Operation = "Search", Repo = repo.Owner + "/" + repo.Name, Page = request.Page };

                        SearchCodeResult       result;
                        ApiValidationException validationException             = null;
                        ExceptionDispatchInfo  validationExceptionDispatchInfo = null;

                        result = await
                                 _searchThrottler.RunAsync <SearchCodeResult>(
                            async() =>
                        {
                            //  Do a try/catch inside here so that renamed repos don't get logged as failures by the throttler
                            try
                            {
                                return(await _client.Search.SearchCode(request));
                            }
                            catch (ApiValidationException ex) when(handleRenamedRepos)
                            {
                                validationException             = ex;
                                validationExceptionDispatchInfo = ExceptionDispatchInfo.Capture(ex);
                                return(null);
                            }
                        },
                            operation
                            );

                        if (result == null && validationException != null)
                        {
                            _logger.Debug(validationException, "Api validation exception for {Operation}, checking for renamed repo", operation);

                            var renameOperation = new { Operation = "RenameCheck", Repo = repo.Owner + "/" + repo.Name };

                            var potentiallyRenamedRepo = await _throttler.RunAsync <Repository>(
                                async() =>
                            {
                                try
                                {
                                    return(await _client.Repository.Get(repo.Owner, repo.Name));
                                }
                                catch (NotFoundException)
                                {
                                    return(null);
                                }
                            },
                                renameOperation
                                );

                            if (potentiallyRenamedRepo == null)
                            {
                                _logger.Information("Repo {Repo} not found", renameOperation.Repo);
                                _storage.SaveNotFound(repo.Owner, repo.Name, true);
                                return(Enumerable.Empty <SearchResult>());
                            }

                            if (potentiallyRenamedRepo.Owner.Login == repo.Owner && potentiallyRenamedRepo.Name == repo.Name)
                            {
                                _logger.Error("Repo was not renamed, Api validation must have failed for some other reason for {Operation}", operation);
                                validationExceptionDispatchInfo.Throw();
                            }

                            var newRepo = repo.Clone();

                            newRepo.Owner = potentiallyRenamedRepo.Owner.Login;
                            newRepo.Name  = potentiallyRenamedRepo.Name;

                            _logger.Information("Repo {OldRepo} has been renamed to {Repo}", renameOperation.Repo, newRepo.Owner + "/" + newRepo.Name);

                            _storage.SaveRenamedRepo(repo.Owner, repo.Name, newRepo);

                            return(await SearchRepoAsync(newRepo, false));
                        }

                        foreach (var item in result.Items)
                        {
                            string destFile = _storage.GetFilePath(repo.Owner, repo.Name, item.Path);
                            if (Path.GetFileName(destFile).Equals("project.json", StringComparison.OrdinalIgnoreCase))
                            {
                                ret.Add(new SearchResult(item));
                            }
                            else
                            {
                                _logger.Information("{Path} was not a project.json file in {Repo}, ignoring", item.Path, repo.Owner + "/" + repo.Name);
                            }
                        }

                        if (result.IncompleteResults)
                        {
                            _logger.Error("Incomplete search results for {Repo}", repo.Owner + "/" + repo.Name);
                            break;
                        }

                        totalResultsReturned += result.Items.Count;

                        if (totalResultsReturned >= result.TotalCount)
                        {
                            break;
                        }
                        else
                        {
                            request.Page += 1;
                        }
                    }

                    _storage.RecordRepoResults(repo.Owner, repo.Name, ret);
                    _logger.Information("Completed searching repo {Repo}", repo.Owner + "/" + repo.Name);
                }


                return(ret);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "{Operation} failed", operation);
                return(Enumerable.Empty <SearchResult>());
            }
        }