Skip to content

Commit 480a7ba

Browse files
authored
Merge pull request #2160 from Urgau/gh-range-diff-misc-2
Misc changes for our range-diff
2 parents 8ffd950 + 9420439 commit 480a7ba

File tree

2 files changed

+182
-17
lines changed

2 files changed

+182
-17
lines changed

src/gh_range_diff.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ fn process_old_new(
315315
"#
316316
)?;
317317

318+
let mut diff_displayed = 0;
319+
318320
let mut process_diffs = |filename, old_patch, new_patch| -> anyhow::Result<()> {
319321
// Removes diff markers to avoid false-positives
320322
let new_marker = format!("@@ {filename}:");
@@ -346,6 +348,7 @@ fn process_old_new(
346348
html,
347349
r#"<details open=""><summary>{filename} <a href="{before_href}">before</a> <a href="{after_href}">after</a></summary><pre class="diff-content">{diff}</pre></details>"#
348350
)?;
351+
diff_displayed += 1;
349352
}
350353
Ok(())
351354
};
@@ -379,6 +382,11 @@ fn process_old_new(
379382
process_diffs(filename, "", &*new_file.patch)?;
380383
}
381384

385+
// Print message when there aren't any differences
386+
if diff_displayed == 0 {
387+
writeln!(html, "<p>No differences</p>")?;
388+
}
389+
382390
writeln!(
383391
html,
384392
r#"
Lines changed: 174 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
use anyhow::Context as _;
22

33
use crate::config::RangeDiffConfig;
4+
use crate::db::issue_data::IssueData;
5+
use crate::github::CommitBase;
46
use crate::github::GithubCompare;
57
use crate::github::IssueRepository;
68
use crate::github::IssuesEvent;
9+
use crate::github::ReportedContentClassifiers;
710
use crate::handlers::Context;
811

12+
/// Key for the state in the database
13+
const RANGE_DIFF_LINK_KEY: &str = "range-diff-link";
14+
15+
/// State stored in the database
16+
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
17+
struct RangeDiffLinkState {
18+
/// ID of the most recent range-diff comment.
19+
last_comment: Option<String>,
20+
}
21+
922
pub(super) async fn handle_event(
1023
ctx: &Context,
1124
host: &str,
@@ -23,25 +36,45 @@ pub(super) async fn handle_event(
2336
};
2437

2538
let base = event.issue.base.as_ref().context("no base ref")?;
26-
let org = event.repository.owner();
27-
let repo = event.repository.name();
39+
let issue_repo = IssueRepository {
40+
organization: event.repository.owner().to_string(),
41+
repository: event.repository.name().to_string(),
42+
};
2843

2944
let compare_before = ctx
3045
.github
31-
.compare(
32-
&IssueRepository {
33-
organization: org.to_string(),
34-
repository: repo.to_string(),
35-
},
36-
&base.sha,
37-
&before,
38-
)
46+
.compare(&issue_repo, &base.sha, &before)
3947
.await
4048
.context("failed to get the before compare")?;
4149

50+
if let Some(message) = changed_base_commit(
51+
host,
52+
&issue_repo,
53+
base,
54+
&compare_before,
55+
compare_after,
56+
before,
57+
after,
58+
) {
59+
// Rebase detected, post a comment linking to our range-diff.
60+
post_new_comment(ctx, event, message).await?;
61+
}
62+
63+
Ok(())
64+
}
65+
66+
fn changed_base_commit(
67+
host: &str,
68+
issue_repo: &IssueRepository,
69+
base: &CommitBase,
70+
compare_before: &GithubCompare,
71+
compare_after: &GithubCompare,
72+
oldhead: &str,
73+
newhead: &str,
74+
) -> Option<String> {
4275
// Does the merge_base_commits differs? No, not a force-push with rebase.
4376
if compare_before.merge_base_commit.sha == compare_after.merge_base_commit.sha {
44-
return Ok(());
77+
return None;
4578
}
4679

4780
let protocol = if host.starts_with("localhost:") {
@@ -51,13 +84,137 @@ pub(super) async fn handle_event(
5184
};
5285

5386
let branch = &base.git_ref;
54-
let (oldbase, oldhead) = (&compare_before.merge_base_commit.sha, before);
55-
let (newbase, newhead) = (&compare_after.merge_base_commit.sha, after);
87+
let oldbase = &compare_before.merge_base_commit.sha;
88+
let newbase = &compare_after.merge_base_commit.sha;
5689

57-
// Rebase detected, post a comment to our range-diff.
58-
event.issue.post_comment(&ctx.github,
59-
&format!(r#"This PR was rebased onto a different {branch} commit! Check out the changes with our [`range-diff`]({protocol}://{host}/gh-range-diff/{org}/{repo}/{oldbase}..{oldhead}/{newbase}..{newhead})."#)
60-
).await.context("failed to post range-diff comment")?;
90+
let message = format!(
91+
r#"This PR was rebased onto a different {branch} commit. Here's a [range-diff]({protocol}://{host}/gh-range-diff/{issue_repo}/{oldbase}..{oldhead}/{newbase}..{newhead}) highlighting what actually changed.
92+
93+
*Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.*"#
94+
);
95+
96+
Some(message)
97+
}
98+
99+
async fn post_new_comment(
100+
ctx: &Context,
101+
event: &IssuesEvent,
102+
message: String,
103+
) -> anyhow::Result<()> {
104+
let mut db = ctx.db.get().await;
105+
let mut state: IssueData<'_, RangeDiffLinkState> =
106+
IssueData::load(&mut db, &event.issue, RANGE_DIFF_LINK_KEY).await?;
107+
108+
// Hide previous range-diff comment.
109+
if let Some(last_comment) = state.data.last_comment {
110+
event
111+
.issue
112+
.hide_comment(
113+
&ctx.github,
114+
&last_comment,
115+
ReportedContentClassifiers::Outdated,
116+
)
117+
.await
118+
.context("failed to hide previous range-diff comment")?;
119+
}
120+
121+
// Post new range-diff comment and remember it.
122+
state.data.last_comment = Some(
123+
event
124+
.issue
125+
.post_comment(&ctx.github, &message)
126+
.await
127+
.context("failed to post range-diff comment")?
128+
.node_id,
129+
);
130+
131+
state.save().await?;
61132

62133
Ok(())
63134
}
135+
136+
#[cfg(test)]
137+
mod tests {
138+
use crate::handlers::check_commits::dummy_commit_from_body;
139+
140+
use super::changed_base_commit;
141+
142+
#[test]
143+
fn unchanged_base_commit() {
144+
assert_eq!(
145+
changed_base_commit(
146+
"mytriagebot.com",
147+
&crate::github::IssueRepository {
148+
organization: "rust-lang".to_string(),
149+
repository: "rust".to_string()
150+
},
151+
&crate::github::CommitBase {
152+
sha: "sha-base-commit".to_string(),
153+
git_ref: "master".to_string(),
154+
repo: None
155+
},
156+
&crate::github::GithubCompare {
157+
base_commit: dummy_commit_from_body("base-commit-sha", "base-commit-body"),
158+
merge_base_commit: dummy_commit_from_body(
159+
"same-merge-commit",
160+
"merge-commit-body"
161+
),
162+
files: vec![]
163+
},
164+
&crate::github::GithubCompare {
165+
base_commit: dummy_commit_from_body("base-commit-sha", "base-commit-body"),
166+
merge_base_commit: dummy_commit_from_body(
167+
"same-merge-commit",
168+
"merge-commit-body"
169+
),
170+
files: vec![]
171+
},
172+
"oldhead",
173+
"newhead"
174+
),
175+
None
176+
);
177+
}
178+
179+
#[test]
180+
fn changed_base_commit_() {
181+
assert_eq!(
182+
changed_base_commit(
183+
"mytriagebot.com",
184+
&crate::github::IssueRepository {
185+
organization: "rust-lang".to_string(),
186+
repository: "rust".to_string()
187+
},
188+
&crate::github::CommitBase {
189+
sha: "sha-base-commit".to_string(),
190+
git_ref: "master".to_string(),
191+
repo: None
192+
},
193+
&crate::github::GithubCompare {
194+
base_commit: dummy_commit_from_body("base-commit-sha", "base-commit-body"),
195+
merge_base_commit: dummy_commit_from_body(
196+
"before-merge-commit",
197+
"merge-commit-body"
198+
),
199+
files: vec![]
200+
},
201+
&crate::github::GithubCompare {
202+
base_commit: dummy_commit_from_body("base-commit-sha", "base-commit-body"),
203+
merge_base_commit: dummy_commit_from_body(
204+
"after-merge-commit",
205+
"merge-commit-body"
206+
),
207+
files: vec![]
208+
},
209+
"oldhead",
210+
"newhead"
211+
),
212+
Some(
213+
r#"This PR was rebased onto a different master commit. Here's a [range-diff](https://mytriagebot.com/gh-range-diff/rust-lang/rust/before-merge-commit..oldhead/after-merge-commit..newhead) highlighting what actually changed.
214+
215+
*Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.*"#
216+
.to_string()
217+
)
218+
);
219+
}
220+
}

0 commit comments

Comments
 (0)