git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC/PATCH] gitweb: Paginate project list

From
Jakub Narebski <jnareb@gmail.com>
Date
May 10, 2008, 09:28 UTC
Message-ID
<200805101128.59313.jnareb@gmail.com>
In-Reply-To
<200805091523.24591.jnareb@gmail.com>

Divide projects list and project search results into pages of $page_size (currently 100) elements. Pagination links look like shown below:

  first prev 1 2 3 *4* 5 6 next last

where *4* denotes current page, is in bold, and isn't a link. This would need to be improved for extremely large number of projects (repositories), where number of projects divided by page size is very large.

Currently pagination interacts with sorting in a bit strange way. When clicking on "sort by" link when on some later page the result is not this page sorted, by given page of sorted output. Perhaps "sort by" links should always show first page...

git_project_list_body() subroutine takes care to fill field (key) we sort by for all projects, sort by given ordering, and fill the rest of project info only for projects shown.

NOTE: currently code is not optimal, as it contains a few unnecessary
array copying, or array fragment copying.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This patch depends on earlier "gitweb: Project search", but conceptually
they are independent; probably fill_project_list_info() improvement to
do partial filling should be in seaparet commit...
 gitweb/gitweb.perl |   57 ++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 7e1a9b4..716f7ad 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -3709,10 +3709,10 @@ sub print_sort_th_num {
 sub git_project_list_body {
 	my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
 
+	$order ||= $default_projects_order;
 	my ($check_forks) = gitweb_check_feature('forks');
-	my @projects = fill_project_list_info($projlist, $check_forks);
+	my @projects = fill_project_list_info($projlist, $check_forks, $order);
 
-	$order ||= $default_projects_order;
 	$from = 0 unless defined $from;
 	$to = $#projects if (!defined $to || $#projects < $to);
 
@@ -3733,9 +3733,10 @@ sub git_project_list_body {
 		print "<th></th>\n" . # for links
 		      "</tr>\n";
 	}
+	@projects = @projects[$from..$to];
+	@projects = fill_project_list_info(\@projects, $check_forks);
 	my $alternate = 1;
-	for (my $i = $from; $i <= $to; $i++) {
-		my $pr = $projects[$i];
+	foreach my $pr (@projects) {
 		if ($alternate) {
 			print "<tr class=\"dark\">\n";
 		} else {
@@ -4066,6 +4067,46 @@ sub git_project_list {
 		die_error(undef, "No projects found");
 	}
 
+	my $page_size = 100;
+	# +1 for incomplete page (not having $page_size items)
+	my $npages = int(@list / $page_size)+((@list % $page_size) > 0);
+	# pages are numbered 0..$npages-1
+	$page = 0 if (!defined $page || $page < 0);
+	$page = $npages-1 if ($page >= $npages);
+	my $paging_nav;
+
+	if ($npages > 1) {
+		my @paging = ();
+		push @paging, $cgi->a({-href => href(-replay=>1, page=>0)},
+		                      "first");
+		if ($page > 0) {
+			push @paging, $cgi->a({-href => href(-replay=>1, page=>$page-1),
+			                       -accesskey => "p", -title => "Alt-p"},
+			                      "prev");
+		} else {
+			push @paging, "prev";
+		}
+		for (my $pg = 0; $pg < $npages; $pg++) {
+			# links to individual pages are numbered 1..$npages
+			if ($page == $pg) {
+				push @paging, '<b>'.($pg+1).'</b>';
+			} else {
+				push @paging, $cgi->a({-href => href(-replay=>1, page=>$pg)},
+				                      $pg+1);
+			}
+		}
+		if ($page < $npages-1) {
+			push @paging, $cgi->a({-href => href(-replay=>1, page=>$page+1),
+			                       -accesskey => "n", -title => "Alt-n"},
+			                      "next");
+		} else {
+			push @paging, "next";
+		}
+		push @paging, $cgi->a({-href => href(-replay=>1, page=>$npages-1)},
+		                      "last");
+		$paging_nav = join(' &sdot; ', @paging);
+	}
+
 	git_header_html();
 	if (-f $home_text) {
 		print "<div class=\"index_include\">\n";
@@ -4081,10 +4122,14 @@ sub git_project_list {
 		if (defined $searchtype) {
 			filter_project_list(\@list, $searchtype, $search_regexp)
 				unless ($searchtype eq 'list_all');
-			git_project_list_body(\@list, $order);
+			git_project_list_body(\@list, $order,
+			                      $page*$page_size, ($page+1)*$page_size - 1,
+			                      $paging_nav);
 		}
 	} else {
-		git_project_list_body(\@list, $order);
+		git_project_list_body(\@list, $order,
+		                      $page*$page_size, ($page+1)*$page_size - 1,
+		                      $paging_nav);
 	}
 	git_footer_html();
 }
-- 
1.5.5
Previous: Jakub NarebskiNext: J.H.
Message 7 of 20 in “gitweb: Simplify git_project_list_body”
  1. gitweb: Simplify git_project_list_bodyJakub Narebski, May 1, 2008
  2. gitweb: Allow project description in project_index fileJakub Narebski, May 2, 2008
  3. Miklos VajnaMay 2, 2008
  4. gitweb: Allow project description in project_index fileJakub Narebski, May 3, 2008
  5. Miklos VajnaMay 4, 2008
  6. gitweb: Project searchJakub Narebski, May 9, 2008
  7. gitweb: Paginate project listJakub Narebski, May 10, 2008
  8. J.H.May 10, 2008
  9. Jakub NarebskiMay 10, 2008
  10. J.H.May 11, 2008
  11. Jakub NarebskiMay 11, 2008
  12. Jakub NarebskiMay 12, 2008
  13. Lars HjemliMay 12, 2008
  14. Jakub NarebskiMay 13, 2008
  15. Lars HjemliMay 13, 2008
  16. Jakub NarebskiMay 13, 2008
  17. Kristian HøgsbergMay 13, 2008
  18. Lars HjemliMay 13, 2008
  19. Jakub NarebskiMay 13, 2008
  20. Jakub NarebskiMay 14, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.