Skip to content

Commit 742b66b

Browse files
authored
Merge pull request #1850 from Urgau/rendered_link_push+
Handle pushes and rename for rendered links
2 parents a5f31cd + 18de61a commit 742b66b

File tree

1 file changed

+69
-49
lines changed

1 file changed

+69
-49
lines changed

src/handlers/rendered_link.rs

Lines changed: 69 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::borrow::Cow;
2+
13
use anyhow::bail;
24

35
use crate::{
@@ -34,65 +36,83 @@ async fn add_rendered_link(ctx: &Context, e: &IssuesEvent, prefix: &str) -> anyh
3436
if e.action == IssuesAction::Opened
3537
|| e.action == IssuesAction::Closed
3638
|| e.action == IssuesAction::Reopened
39+
|| e.action == IssuesAction::Synchronize
3740
{
3841
let files = e.issue.files(&ctx.github).await?;
3942

40-
if let Some(file) = files.iter().find(|f| f.filename.starts_with(prefix)) {
41-
let head = e.issue.head.as_ref().unwrap();
42-
let base = e.issue.base.as_ref().unwrap();
43+
let rendered_link = files
44+
.iter()
45+
.find(|f| f.filename.starts_with(prefix))
46+
.map(|file| {
47+
let head = e.issue.head.as_ref().unwrap();
48+
let base = e.issue.base.as_ref().unwrap();
4349

44-
// This URL should be stable while the PR is open, even if the
45-
// user pushes new commits.
46-
//
47-
// It will go away if the user deletes their branch, or if
48-
// they reset it (such as if they created a PR from master).
49-
// That should usually only happen after the PR is closed
50-
// a which point we switch to a SHA-based url.
51-
//
52-
// If the PR is merged we use a URL that points to the actual
53-
// repository, as to be resilient to branch deletion, as well
54-
// be in sync with current "master" branch.
55-
//
56-
// For a PR "octocat:master" <- "Bob:patch-1", we generate,
57-
// - if merged: `https://github.com/octocat/REPO/blob/master/FILEPATH`
58-
// - if open: `https://github.com/Bob/REPO/blob/patch-1/FILEPATH`
59-
// - if closed: `https://github.com/octocat/REPO/blob/SHA/FILEPATH`
60-
let rendered_link = format!(
61-
"[Rendered](https://github.com/{}/blob/{}/{})",
62-
if e.issue.merged || e.action == IssuesAction::Closed {
63-
&e.repository.full_name
64-
} else {
65-
&head.repo.full_name
66-
},
67-
if e.issue.merged {
68-
&base.git_ref
69-
} else if e.action == IssuesAction::Closed {
70-
&head.sha
71-
} else {
72-
&head.git_ref
73-
},
74-
file.filename
75-
);
50+
// This URL should be stable while the PR is open, even if the
51+
// user pushes new commits.
52+
//
53+
// It will go away if the user deletes their branch, or if
54+
// they reset it (such as if they created a PR from master).
55+
// That should usually only happen after the PR is closed
56+
// a which point we switch to a SHA-based url.
57+
//
58+
// If the PR is merged we use a URL that points to the actual
59+
// repository, as to be resilient to branch deletion, as well
60+
// be in sync with current "master" branch.
61+
//
62+
// For a PR "octocat:master" <- "Bob:patch-1", we generate,
63+
// - if merged: `https://github.com/octocat/REPO/blob/master/FILEPATH`
64+
// - if open: `https://github.com/Bob/REPO/blob/patch-1/FILEPATH`
65+
// - if closed: `https://github.com/octocat/REPO/blob/SHA/FILEPATH`
66+
format!(
67+
"[Rendered](https://github.com/{}/blob/{}/{})",
68+
if e.issue.merged || e.action == IssuesAction::Closed {
69+
&e.repository.full_name
70+
} else {
71+
&head.repo.full_name
72+
},
73+
if e.issue.merged {
74+
&base.git_ref
75+
} else if e.action == IssuesAction::Closed {
76+
&head.sha
77+
} else {
78+
&head.git_ref
79+
},
80+
file.filename
81+
)
82+
});
7683

77-
let new_body = if !e.issue.body.contains("[Rendered]") {
84+
let new_body: Cow<'_, str> = if !e.issue.body.contains("[Rendered]") {
85+
if let Some(rendered_link) = rendered_link {
7886
// add rendered link to the end of the body
79-
format!("{}\n\n{rendered_link}", e.issue.body)
80-
} else if let Some(start_pos) = e.issue.body.find("[Rendered](") {
81-
let Some(end_offset) = &e.issue.body[start_pos..].find(')') else {
82-
bail!("no `)` after `[Rendered]` found")
83-
};
87+
format!("{}\n\n{rendered_link}", e.issue.body).into()
88+
} else {
89+
// or return the original body since we don't have
90+
// a rendered link to add
91+
e.issue.body.as_str().into()
92+
}
93+
} else if let Some(start_pos) = e.issue.body.find("[Rendered](") {
94+
let Some(end_offset) = &e.issue.body[start_pos..].find(')') else {
95+
bail!("no `)` after `[Rendered]` found")
96+
};
8497

85-
// replace the current rendered link with the new one
86-
e.issue.body.replace(
98+
// replace the current rendered link with the new one or replace
99+
// it with an empty string if we don't have one
100+
e.issue
101+
.body
102+
.replace(
87103
&e.issue.body[start_pos..=(start_pos + end_offset)],
88-
&rendered_link,
104+
rendered_link.as_deref().unwrap_or(""),
89105
)
90-
} else {
91-
bail!(
92-
"found `[Rendered]` but not it's associated link, can't replace it, bailing out"
93-
)
94-
};
106+
.into()
107+
} else {
108+
bail!(
109+
"found `[Rendered]` but not it's associated link, can't replace it or remove it, bailing out"
110+
)
111+
};
95112

113+
// avoid an expensive GitHub api call by first checking if we actually
114+
// edited the pull request body
115+
if e.issue.body != new_body {
96116
e.issue.edit_body(&ctx.github, &new_body).await?;
97117
}
98118
}

0 commit comments

Comments
 (0)