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/commit/commit_routes.v b/commit/commit_routes.v index 35564987..8c378532 100644 --- a/commit/commit_routes.v +++ b/commit/commit_routes.v @@ -4,6 +4,7 @@ import veb import time import api import git +import os @['/api/v1/:user/:repo_name/:branch_name/commits/count'] fn (mut app App) handle_commits_count(mut ctx Context, username string, repo_name string, branch_name string) veb.Result { @@ -32,7 +33,7 @@ fn (mut app App) handle_commits_count(mut ctx Context, username string, repo_nam // app.debug("${branch} ${count}" ) return ctx.json(api.ApiCommitCount{ success: true - result: count + result: count }) } @@ -140,3 +141,36 @@ pub fn (mut app App) commit(mut ctx Context, username string, repo_name string, return $veb.html() } + +@['/:username/:repo_name/cherry-pick/:hash'; post] +pub fn (mut app App) handle_cherry_pick(mut ctx Context, username string, repo_name string, hash string) veb.Result { + repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() } + if !app.can_admin_repo(ctx, repo) { + return ctx.not_found() + } + branch := ctx.form['branch'] or { repo.primary_branch } + target := ctx.form['target_branch'] or { branch } + if !is_safe_ref(branch) || !is_safe_ref(target) || !is_valid_commit_hash(hash) { + ctx.error('Invalid ref') + return ctx.redirect('/${username}/${repo_name}/-/commits/${target}') + } + worktree := os.join_path(os.temp_dir(), 'gitly_cp_${os.getpid()}_${time.now().unix_nano()}') + os.mkdir_all(worktree) or { + ctx.error('Failed to create worktree: ') + return ctx.redirect('/${username}/${repo_name}/-/commits/${target}') + } + defer { os.rmdir_all(worktree) or {} } + add_res := git.Git.exec_in_dir(repo.git_dir, ['worktree', 'add', '--force', worktree, target]) + if add_res.exit_code != 0 { + ctx.error('Failed to prepare worktree: ') + return ctx.redirect('/${username}/${repo_name}/-/commits/${target}') + } + cp_res := git.Git.exec_in_dir(worktree, ['cherry-pick', hash]) + remove_res := git.Git.exec_in_dir(repo.git_dir, ['worktree', 'remove', '--force', worktree]) + if cp_res.exit_code != 0 { + ctx.error('Cherry-pick failed: ') + return ctx.redirect('/${username}/${repo_name}/-/commits/${target}') + } + _ = remove_res + return ctx.redirect('/${username}/${repo_name}/-/commits/${target}') +} 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