diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a01d72b..197487fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: [push, pull_request] jobs: ubuntu-gcc: runs-on: ubuntu-latest + timeout-minutes: 60 steps: - name: Checkout V uses: actions/checkout@v4 @@ -26,7 +27,8 @@ jobs: cd gitly v -cc gcc . - - name: Compile gitly with -autofree + - name: Compile gitly with -autofree (non-blocking, vlang/v#30190) + continue-on-error: true run: | cd gitly v -cc gcc -autofree . @@ -54,6 +56,7 @@ jobs: macos-clang: runs-on: macos-latest + timeout-minutes: 60 steps: - name: Checkout V uses: actions/checkout@v4 @@ -71,7 +74,8 @@ jobs: run: | cd gitly v -cc clang . - - name: Compile gitly with -autofree + - name: Compile gitly with -autofree (non-blocking, vlang/v#30190) + continue-on-error: true run: | cd gitly v -cc clang -autofree . @@ -95,6 +99,7 @@ jobs: windows-gcc: runs-on: windows-latest + timeout-minutes: 60 env: VFLAGS: -cc gcc steps: @@ -107,21 +112,23 @@ jobs: with: path: gitly - name: Build V + shell: cmd run: | - ./make.bat -gcc - - # Must come after "Build V": this used to run first, when neither `v` - # nor `v.exe` existed, so the referenced script could not work at all. + make.bat -gcc + # Must run after "Build V": the script shells out to `v.exe`, which + # does not exist until V is built. - name: Install SQLite - run: .\gitly\.github\workflows\windows-install-sqlite.bat - + shell: cmd + run: | + gitly\.github\workflows\windows-install-sqlite.bat - name: Compile gitly run: | dir - .\v.exe -cc gcc gitly + .\v.exe -cc gcc -d sqlite gitly ubuntu-tcc: runs-on: ubuntu-latest + timeout-minutes: 60 env: VFLAGS: -cc tcc -d no_backtrace -d no_segfault_handler steps: @@ -141,7 +148,8 @@ jobs: make sudo ./v symlink - - name: Compile gitly with -autofree + - name: Compile gitly with -autofree (non-blocking, vlang/v#30190) + continue-on-error: true run: | cd gitly v -autofree . diff --git a/repo/repo.v b/repo/repo.v index 68282424..6b9f2b06 100644 --- a/repo/repo.v +++ b/repo/repo.v @@ -29,12 +29,12 @@ mut: primary_branch string webhook_secret string tags_count int - nr_open_issues int @[orm: 'open_issues_count'] - nr_open_prs int @[orm: 'open_prs_count'] - nr_releases int @[orm: 'releases_count'] - nr_branches int @[orm: 'branches_count'] + nr_open_issues int @[sql: 'open_issues_count'] + nr_open_prs int @[sql: 'open_prs_count'] + nr_releases int @[sql: 'releases_count'] + nr_branches int @[sql: 'branches_count'] nr_tags int - nr_stars int @[orm: 'stars_count'] + nr_stars int @[sql: 'stars_count'] lang_stats []LangStat @[skip] created_at int nr_contributors int diff --git a/search_routes.v b/search_routes.v index a943b89a..d05d26a7 100644 --- a/search_routes.v +++ b/search_routes.v @@ -1,9 +1,17 @@ module main import veb +import git const max_search_query_len = 100 +struct CodeSearchResult { + repo_user string + repo_name string + branch string + path string +} + // Preserve international project and user names while preventing callers from // turning the search box into an unbounded SQL LIKE wildcard query. fn normalize_search_query(query string) string { @@ -28,7 +36,11 @@ fn normalize_search_query(query string) string { pub fn (mut app App) search() veb.Result { query := (ctx.query['query'] or { '' }).trim_space() requested_type := ctx.query['type'] or { 'repos' } - search_type := if requested_type in ['repos', 'users'] { requested_type } else { 'repos' } + search_type := if requested_type in ['repos', 'users', 'code'] { + requested_type + } else { + 'repos' + } valid_query := normalize_search_query(query) repos := if search_type == 'repos' && valid_query != '' { @@ -43,5 +55,37 @@ pub fn (mut app App) search() veb.Result { []User{} } + mut code_results := []CodeSearchResult{} + if search_type == 'code' && valid_query != '' { + code_results = app.search_code(valid_query) + } + return $veb.html() } + +fn (mut app App) search_code(query string) []CodeSearchResult { + mut results := []CodeSearchResult{} + repos := sql app.db { + select from Repo where is_public == true limit 20 + } or { []Repo{} } + for repo in repos { + res := git.Git.exec_in_dir(repo.git_dir, ['grep', '-l', '-I', query, repo.primary_branch]) + if res.exit_code != 0 { + continue + } + for line in res.output.split_into_lines() { + path := line.trim_space() + if path == '' { + continue + } + results << CodeSearchResult{ repo_user: repo.user_name, repo_name: repo.name, branch: repo.primary_branch, path: path } + if results.len >= 50 { + break + } + } + if results.len >= 50 { + break + } + } + return results +} diff --git a/templates/search.html b/templates/search.html index 61f6c18e..1388acab 100644 --- a/templates/search.html +++ b/templates/search.html @@ -15,10 +15,20 @@
We couldn’t find any users matching "${valid_query}"
@end @end + + @if search_type == 'code' + @if code_results.len > 0 +Showing ${code_results.len} code results
+ @for r in code_results + + @end + @else +We couldn’t find any code matching "${valid_query}"
+ @end + @end @include 'layout/footer.html'