| 791 | 791 | | ignore_checks: bool, |
| 792 | 792 | | honor_bypass: bool, |
| 793 | 793 | | ) -> Result<Gate> { |
| 794 | | − | self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, None).await |
| 794 | + | self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, None, None).await |
| 795 | 795 | | } |
| 796 | 796 | | |
| 797 | + | /// `merge_gate` with whether it is behind already worked out (from |
| 798 | + | /// what was stored with its mergeability, or asked once for this |
| 799 | + | /// request), so that showing a pull request does not ask repos again. |
| 800 | + | pub(crate) async fn merge_gate_seen(&self, repo: &Repo, pull: &Pull, actor: Option<&User>, behind: bool) -> Result<Gate> { |
| 801 | + | self.merge_gate_at(repo, pull, actor, false, true, None, None, Some(behind)).await |
| 802 | + | } |
| 803 | + | |
| 797 | 804 | | /// `merge_gate` for a merge by `method`: rules that allow only some |
| 798 | 805 | | /// methods, and linear history, judge it too. Without a method they do |
| 799 | 806 | | /// not, as for showing what a pull request still needs. |
| ⋯ |
| 806 | 813 | | honor_bypass: bool, |
| 807 | 814 | | method: MergeMethod, |
| 808 | 815 | | ) -> Result<Gate> { |
| 809 | | − | self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, Some(method)).await |
| 816 | + | self.merge_gate_at(repo, pull, actor, ignore_checks, honor_bypass, None, Some(method), None).await |
| 810 | 817 | | } |
| 811 | 818 | | |
| 812 | 819 | | /// Re-evaluate current reviews and rules against the exact combined state. |
| ⋯ |
| 828 | 835 | | ) -> Result<Gate> { |
| 829 | 836 | | // The tested state was built by the entry's method (queue.rs), which |
| 830 | 837 | | // the rules judge as they are now. |
| 831 | | − | let gate = self.merge_gate_at(repo, pull, Some(actor), false, true, Some((commit, statuses)), Some(method)).await?; |
| 838 | + | let gate = self.merge_gate_at(repo, pull, Some(actor), false, true, Some((commit, statuses)), Some(method), None).await?; |
| 832 | 839 | | Ok(if landing_honors_bypass(actor, bypass_rules) { gate } else { gate.without_bypass() }) |
| 833 | 840 | | } |
| 834 | 841 | | |
| 842 | + | #[allow(clippy::too_many_arguments)] |
| 835 | 843 | | async fn merge_gate_at( |
| 836 | 844 | | &self, |
| 837 | 845 | | repo: &Repo, |
| ⋯ |
| 841 | 849 | | honor_bypass: bool, |
| 842 | 850 | | tested: Option<(&str, Vec<g1t_contracts::work::CommitStatus>)>, |
| 843 | 851 | | method: Option<MergeMethod>, |
| 852 | + | known_behind: Option<bool>, |
| 844 | 853 | | ) -> Result<Gate> { |
| 845 | 854 | | let tested_commit = tested.as_ref().map(|(commit, _)| *commit); |
| 846 | 855 | | let tested_statuses = tested.as_ref().map(|(_, statuses)| statuses.clone()); |
| ⋯ |
| 880 | 889 | | async { |
| 881 | 890 | | // The repository service verifies ancestry and CAS for the |
| 882 | 891 | | // combined commit; the original PR may legitimately be behind. |
| 883 | | − | if tested_commit.is_some() { Ok(false) } else { self.is_behind(pull).await } |
| 892 | + | match (tested_commit, known_behind) { |
| 893 | + | (Some(_), _) => Ok(false), |
| 894 | + | (None, Some(behind)) => Ok(behind), |
| 895 | + | (None, None) => self.is_behind(pull).await, |
| 896 | + | } |
| 884 | 897 | | }, |
| 885 | 898 | | async { |
| 886 | 899 | | if needs_owners { self.code_owners_gap(&owners_settings, pull).await } else { Ok(None) } |