//! Create a review comment for a pull request
//!
//! Creates a review comment in the pull request diff. To add a regular comment to a pull request timeline, see "[Create an issue comment](https://docs.github.com/rest/reference/issues#create-an-issue-comment)." We recommend creating a review comment using `line`, `side`, and optionally `start_line` and `start_side` if your comment applies to more than one line in the pull request diff.
//!
//! The `position` parameter is deprecated. If you use `position`, the `line`, `side`, `start_line`, and `start_side` parameters are not required.
//!
//! **Note:** The position value equals the number of lines down from the first "@@" hunk header in the file you want to add a comment. The line just below the "@@" line is position 1, the next line is position 2, and so on. The position in the diff continues to increase through lines of whitespace and additional hunks until the beginning of a new file.
//!
//! This endpoint triggers [notifications](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/about-notifications). Creating content too quickly using this endpoint may result in secondary rate limiting. See "[Secondary rate limits](https://docs.github.com/rest/overview/resources-in-the-rest-api#secondary-rate-limits)" and "[Dealing with secondary rate limits](https://docs.github.com/rest/guides/best-practices-for-integrators#dealing-with-secondary-rate-limits)" for details.
//!
//! [API method documentation](https://docs.github.com/rest/reference/pulls#create-a-review-comment-for-a-pull-request)
pub struct Content<Body>
{
body: Body,
content_type_value: Option<::std::borrow::Cow<'static, [u8]>>,
}
impl<Body> Content<Body> {
pub fn new(body: Body) -> Self {
Self { body, content_type_value: None }
}
#[must_use]
pub fn with_content_type(mut self, content_type: impl Into<::std::borrow::Cow<'static, [u8]>>) -> Self {
self.content_type_value = Some(content_type.into());
self
}
fn content_type(&self) -> Option<&[u8]> {
self.content_type_value.as_deref()
}
fn into_body(self) -> Body {
self.body
}
}
fn url_string(
base_url: &str,
p_owner: &str,
p_repo: &str,
p_pull_number: i64,
) -> Result<String, crate::v1_1_4::ApiError> {
let trimmed = if base_url.is_empty() {
"https://api.github.com"
} else {
base_url.trim_end_matches('/')
};
let mut url = String::with_capacity(trimmed.len() + 43);
url.push_str(trimmed);
url.push_str("/repos/");
::querylizer::Simple::extend(&mut url, &p_owner, false, &::querylizer::encode_path)?;
url.push('/');
::querylizer::Simple::extend(&mut url, &p_repo, false, &::querylizer::encode_path)?;
url.push_str("/pulls/");
::querylizer::Simple::extend(&mut url, &p_pull_number, false, &::querylizer::encode_path)?;
url.push_str("/comments");
Ok(url)
}
#[cfg(feature = "hyper")]
pub fn http_builder(
base_url: &str,
p_owner: &str,
p_repo: &str,
p_pull_number: i64,
h_user_agent: &str,
h_accept: ::std::option::Option<&str>,
) -> Result<::http::request::Builder, crate::v1_1_4::ApiError> {
let url = url_string(
base_url,
p_owner,
p_repo,
p_pull_number,
)?;
let mut builder = ::http::request::Request::post(url);
builder = builder.header(
"User-Agent",
&::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?
);
if let Some(value) = &h_accept {
builder = builder.header(
"Accept",
&::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?
);
}
Ok(builder)
}
#[cfg(feature = "hyper")]
pub fn hyper_request(
mut builder: ::http::request::Builder,
content: Content<::hyper::Body>,
) -> Result<::http::request::Request<::hyper::Body>, crate::v1_1_4::ApiError>
{
if let Some(content_type) = content.content_type() {
builder = builder.header(::http::header::CONTENT_TYPE, content_type);
}
Ok(builder.body(content.into_body())?)
}
#[cfg(feature = "hyper")]
impl From<::hyper::Body> for Content<::hyper::Body> {
fn from(body: ::hyper::Body) -> Self {
Self::new(body)
}
}
#[cfg(feature = "reqwest")]
pub fn reqwest_builder(
base_url: &str,
p_owner: &str,
p_repo: &str,
p_pull_number: i64,
h_user_agent: &str,
h_accept: ::std::option::Option<&str>,
) -> Result<::reqwest::Request, crate::v1_1_4::ApiError> {
let url = url_string(
base_url,
p_owner,
p_repo,
p_pull_number,
)?;
let reqwest_url = ::reqwest::Url::parse(&url)?;
let mut request = ::reqwest::Request::new(::reqwest::Method::POST, reqwest_url);
let headers = request.headers_mut();
headers.append(
"User-Agent",
::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?.try_into()?
);
if let Some(value) = &h_accept {
headers.append(
"Accept",
::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?.try_into()?
);
}
Ok(request)
}
#[cfg(feature = "reqwest")]
pub fn reqwest_request(
mut builder: ::reqwest::Request,
content: Content<::reqwest::Body>,
) -> Result<::reqwest::Request, crate::v1_1_4::ApiError> {
if let Some(content_type) = content.content_type() {
builder.headers_mut().append(
::reqwest::header::HeaderName::from_static("content-type"),
::reqwest::header::HeaderValue::try_from(content_type)?,
);
}
*builder.body_mut() = Some(content.into_body());
Ok(builder)
}
#[cfg(feature = "reqwest")]
impl From<::reqwest::Body> for Content<::reqwest::Body> {
fn from(body: ::reqwest::Body) -> Self {
Self::new(body)
}
}
#[cfg(feature = "reqwest-blocking")]
pub fn reqwest_blocking_builder(
base_url: &str,
p_owner: &str,
p_repo: &str,
p_pull_number: i64,
h_user_agent: &str,
h_accept: ::std::option::Option<&str>,
) -> Result<::reqwest::blocking::Request, crate::v1_1_4::ApiError> {
let url = url_string(
base_url,
p_owner,
p_repo,
p_pull_number,
)?;
let reqwest_url = ::reqwest::Url::parse(&url)?;
let mut request = ::reqwest::blocking::Request::new(::reqwest::Method::POST, reqwest_url);
let headers = request.headers_mut();
headers.append(
"User-Agent",
::querylizer::Simple::to_string(&h_user_agent, false, &::querylizer::passthrough)?.try_into()?
);
if let Some(value) = &h_accept {
headers.append(
"Accept",
::querylizer::Simple::to_string(value, false, &::querylizer::passthrough)?.try_into()?
);
}
Ok(request)
}
#[cfg(feature = "reqwest-blocking")]
pub fn reqwest_blocking_request(
mut builder: ::reqwest::blocking::Request,
content: Content<::reqwest::blocking::Body>,
) -> Result<::reqwest::blocking::Request, crate::v1_1_4::ApiError> {
if let Some(content_type) = content.content_type() {
builder.headers_mut().append(
::reqwest::header::HeaderName::from_static("content-type"),
::reqwest::header::HeaderValue::try_from(content_type)?,
);
}
*builder.body_mut() = Some(content.into_body());
Ok(builder)
}
#[cfg(feature = "reqwest-blocking")]
impl From<::reqwest::blocking::Body> for Content<::reqwest::blocking::Body> {
fn from(body: ::reqwest::blocking::Body) -> Self {
Self::new(body)
}
}
/// Types for body parameter in [`super::pulls_create_review_comment`]
pub mod body {
#[allow(non_snake_case)]
#[derive(Clone, Eq, PartialEq, Debug, Default, ::serde::Serialize, ::serde::Deserialize)]
pub struct Json<'a> {
/// The text of the review comment.
pub body: ::std::borrow::Cow<'a, str>,
/// The SHA of the commit needing a comment. Not using the latest commit SHA may render your comment outdated if a subsequent commit modifies the line you specify as the `position`.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub commit_id: ::std::option::Option<::std::borrow::Cow<'a, str>>,
/// The relative path to the file that necessitates a comment.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub path: ::std::option::Option<::std::borrow::Cow<'a, str>>,
/// **This paramter is deprecated. Use `line` instead**. The position in the diff where you want to add a review comment. Note this value is not the same as the line number in the file. For help finding the position value, read the note above.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub position: ::std::option::Option<i64>,
/// In a split diff view, the side of the diff that the pull request's changes appear on. Can be `LEFT` or `RIGHT`. Use `LEFT` for deletions that appear in red. Use `RIGHT` for additions that appear in green or unchanged lines that appear in white and are shown for context. For a multi-line comment, side represents whether the last line of the comment range is a deletion or addition. For more information, see "[Diff view options](https://docs.github.com/en/articles/about-comparing-branches-in-pull-requests#diff-view-options)" in the GitHub Help documentation.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub side: ::std::option::Option<::std::borrow::Cow<'a, str>>,
/// The line of the blob in the pull request diff that the comment applies to. For a multi-line comment, the last line of the range that your comment applies to.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub line: ::std::option::Option<i64>,
/// **Required when using multi-line comments unless using `in_reply_to`**. The `start_line` is the first line in the pull request diff that your multi-line comment applies to. To learn more about multi-line comments, see "[Commenting on a pull request](https://docs.github.com/en/articles/commenting-on-a-pull-request#adding-line-comments-to-a-pull-request)" in the GitHub Help documentation.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub start_line: ::std::option::Option<i64>,
/// **Required when using multi-line comments unless using `in_reply_to`**. The `start_side` is the starting side of the diff that the comment applies to. Can be `LEFT` or `RIGHT`. To learn more about multi-line comments, see "[Commenting on a pull request](https://docs.github.com/en/articles/commenting-on-a-pull-request#adding-line-comments-to-a-pull-request)" in the GitHub Help documentation. See `side` in this table for additional context.
#[serde(skip_serializing_if = "Option::is_none", default)]
pub start_side: ::std::option::Option<::std::borrow::Cow<'a, str>>,
/// The ID of the review comment to reply to. To find the ID of a review comment with ["List review comments on a pull request"](#list-review-comments-on-a-pull-request). When specified, all parameters other than `body` in the request body are ignored.
///
/// # Example
///
/// ```json
/// 2
/// ```
#[serde(skip_serializing_if = "Option::is_none", default)]
pub in_reply_to: ::std::option::Option<i64>,
#[serde(flatten)]
pub additionalProperties: ::std::collections::HashMap<::std::borrow::Cow<'a, str>, ::serde_json::value::Value>
}
#[cfg(feature = "hyper")]
impl<'a> TryFrom<&Json<'a>> for super::Content<::hyper::Body> {
type Error = crate::v1_1_4::ApiError;
fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
Ok(
Self::new(::serde_json::to_vec(value)?.into())
.with_content_type(&b"application/json"[..])
)
}
}
#[cfg(feature = "reqwest")]
impl<'a> TryFrom<&Json<'a>> for super::Content<::reqwest::Body> {
type Error = crate::v1_1_4::ApiError;
fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
Ok(
Self::new(::serde_json::to_vec(value)?.into())
.with_content_type(&b"application/json"[..])
)
}
}
#[cfg(feature = "reqwest-blocking")]
impl<'a> TryFrom<&Json<'a>> for super::Content<::reqwest::blocking::Body> {
type Error = crate::v1_1_4::ApiError;
fn try_from(value: &Json<'a>) -> Result<Self, Self::Error> {
Ok(
Self::new(::serde_json::to_vec(value)?.into())
.with_content_type(&b"application/json"[..])
)
}
}
}