commit 7272b60a19e7deee3a1808cbda935e201074c50d from: Omar Polo via: Thomas Adam date: Thu Jun 15 11:27:15 2023 UTC gotwebd: simplify got_get_repo_commits(): don't traverse all the commits! In some cases (e.g. limit=1 for DIFF action) we could end up traversing all the commits instead of fetching just the one requested. Needless to say, this makes the diff page extremely slow. reported by and ok stsp@ commit - 081e3dc235439cbb3e34342349768119ddf4ad49 commit + 7272b60a19e7deee3a1808cbda935e201074c50d blob - 93e82002a185e0494f1787a149ae685c6e173e9f blob + c172d12e5e3176180e7d4fd25b64d9531a5a0ba2 --- gotwebd/got_operations.c +++ gotwebd/got_operations.c @@ -326,7 +326,16 @@ got_get_repo_commits(struct request *c, int limit) struct querystring *qs = t->qs; struct repo_dir *repo_dir = t->repo_dir; char *in_repo_path = NULL, *repo_path = NULL, *file_path = NULL; - int chk_next = 0, chk_multi = 0; + int chk_next = 0; + + if (limit != 1 || srv->max_commits_display == 1) { + /* + * Traverse one commit more than requested to provide + * the next button. + */ + limit++; + chk_next = 1; + } TAILQ_INIT(&refs); @@ -401,41 +410,21 @@ got_get_repo_commits(struct request *c, int limit) &refs, &next_id); if (error) { gotweb_free_repo_commit(repo_commit); + goto done; + } + + if (--limit == 0 && chk_next) { + t->more_id = strdup(repo_commit->commit_id); + if (t->more_id == NULL) + error = got_error_from_errno("strdup"); goto done; } TAILQ_INSERT_TAIL(&t->repo_commits, repo_commit, entry); - if (!chk_multi || limit != 1 || - srv->max_commits_display == 1) { - chk_multi = 1; + if (limit == 0) + goto done; - /* - * check for one more commit before breaking, - * so we know whether to navigate through briefs - * commits and summary - */ - if (chk_next && (qs->action == BRIEFS || - qs->action == COMMITS || qs->action == SUMMARY)) { - t->more_id = strdup(repo_commit->commit_id); - if (t->more_id == NULL) { - error = got_error_from_errno("strdup"); - goto done; - } - got_object_commit_close(commit); - commit = NULL; - TAILQ_REMOVE(&t->repo_commits, repo_commit, - entry); - gotweb_free_repo_commit(repo_commit); - goto done; - } - } - if (error || (limit && --limit == 0)) { - if (qs->file != NULL && *qs->file != '\0') - if (chk_multi == 0) - break; - chk_next = 1; - } if (commit) { got_object_commit_close(commit); commit = NULL;