diff --git a/app/models/changeset.rb b/app/models/changeset.rb index b14b46bc44..49c323acab 100644 --- a/app/models/changeset.rb +++ b/app/models/changeset.rb @@ -191,12 +191,12 @@ class Changeset < ApplicationRecord # Returns the previous changeset def previous - @previous ||= Changeset.where(["id < ? AND repository_id = ?", id, repository_id]).order(id: :desc).first + @previous ||= repository&.previous_changeset(self) end # Returns the next changeset def next - @next ||= Changeset.where(["id > ? AND repository_id = ?", id, repository_id]).order(:id).first + @next ||= repository&.next_changeset(self) end # Creates a new Change from it's common parameters diff --git a/app/models/repository.rb b/app/models/repository.rb index f4092fc96a..9ee21edfe3 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -265,6 +265,34 @@ class Repository < ApplicationRecord @latest_changeset ||= changesets.first end + def previous_changeset(changeset) + changesets. + reorder(nil). + where( + [ + "(#{Changeset.table_name}.committed_on < ? OR " \ + "(#{Changeset.table_name}.committed_on = ? AND #{Changeset.table_name}.id < ?))", + changeset.committed_on, changeset.committed_on, changeset.id + ] + ). + order(committed_on: :desc, id: :desc). + first + end + + def next_changeset(changeset) + changesets. + reorder(nil). + where( + [ + "(#{Changeset.table_name}.committed_on > ? OR " \ + "(#{Changeset.table_name}.committed_on = ? AND #{Changeset.table_name}.id > ?))", + changeset.committed_on, changeset.committed_on, changeset.id + ] + ). + order(committed_on: :asc, id: :asc). + first + end + # Returns the latest changesets for +path+ # Default behaviour is to search in cached changesets def latest_changesets(path, rev, limit=10) diff --git a/app/models/repository/mercurial.rb b/app/models/repository/mercurial.rb index 1d1a3c4ffb..de235effa1 100644 --- a/app/models/repository/mercurial.rb +++ b/app/models/repository/mercurial.rb @@ -128,6 +128,20 @@ class Repository::Mercurial < Repository to_a end + def previous_changeset(changeset) + changesets. + where("#{Changeset.table_name}.id < ?", changeset.id). + reorder(id: :desc). + first + end + + def next_changeset(changeset) + changesets. + where("#{Changeset.table_name}.id > ?", changeset.id). + reorder(id: :asc). + first + end + def is_short_id_in_db? return @is_short_id_in_db unless @is_short_id_in_db.nil? diff --git a/test/unit/changeset_test.rb b/test/unit/changeset_test.rb index 8a753046ef..7a814fe344 100644 --- a/test/unit/changeset_test.rb +++ b/test/unit/changeset_test.rb @@ -468,6 +468,30 @@ class ChangesetTest < ActiveSupport::TestCase assert_equal Changeset.find_by_revision('2'), changeset.previous end + def test_previous_uses_same_order_as_changeset_list + repository = + Repository::Subversion.create!( + :project => Project.find(3), + :url => 'svn://localhost/test/previous-order' + ) + newer_changeset = + Changeset.create!( + :repository => repository, + :committed_on => Time.utc(2025, 4, 8, 10, 0, 0), + :comments => 'Newer changeset', + :revision => 'previous-order-newer' + ) + older_changeset = + Changeset.create!( + :repository => repository, + :committed_on => Time.utc(2025, 4, 7, 10, 0, 0), + :comments => 'Older changeset', + :revision => 'previous-order-older' + ) + + assert_equal older_changeset, newer_changeset.previous + end + def test_previous_nil changeset = Changeset.find_by_revision('1') assert_nil changeset.previous @@ -478,6 +502,30 @@ class ChangesetTest < ActiveSupport::TestCase assert_equal Changeset.find_by_revision('3'), changeset.next end + def test_next_uses_same_order_as_changeset_list + repository = + Repository::Subversion.create!( + :project => Project.find(3), + :url => 'svn://localhost/test/next-order' + ) + newer_changeset = + Changeset.create!( + :repository => repository, + :committed_on => Time.utc(2025, 4, 8, 10, 0, 0), + :comments => 'Newer changeset', + :revision => 'next-order-newer' + ) + older_changeset = + Changeset.create!( + :repository => repository, + :committed_on => Time.utc(2025, 4, 7, 10, 0, 0), + :comments => 'Older changeset', + :revision => 'next-order-older' + ) + + assert_equal newer_changeset, older_changeset.next + end + def test_next_nil changeset = Changeset.find_by_revision('11') assert_nil changeset.next