summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Wahl <mfelsche@users.noreply.github.com>2022-04-19 16:58:29 +0200
committerGitHub <noreply@github.com>2022-04-19 16:58:29 +0200
commit0941fd5190f37d0e47844fb21b04c124b796ea94 (patch)
tree1abbd56c1db0994a7a33440fefc05f2a712deb94
parente24bb4b67c3f990b745d4365dbfcb3805fdd41e8 (diff)
Support for Updating gists via PATCH (#195)
* Support Updating Gists via Patch * Add documentation to gist builder methods. * Ensure that we don't delete files by accident when misusing the builder for updating gist files.
-rw-r--r--src/api/gists.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/api/gists.rs b/src/api/gists.rs
index 4695b57..88948a6 100644
--- a/src/api/gists.rs
+++ b/src/api/gists.rs
@@ -20,6 +20,7 @@ impl<'octo> GistsHandler<'octo> {
}
/// Create a new gist.
+ ///
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// let gitignore = octocrab::instance()
@@ -38,7 +39,31 @@ impl<'octo> GistsHandler<'octo> {
CreateGistBuilder::new(self.crab)
}
+ /// Update an existing gist.
+ ///
+ /// ```no_run
+ /// # async fn run() -> octocrab::Result<()> {
+ /// let gitignore = octocrab::instance()
+ /// .gists()
+ /// .update("aa5a315d61ae9438b18d")
+ /// // Optional Parameters
+ /// .description("Updated!")
+ /// .file("hello_world.rs")
+ /// .rename_to("fibonacci.rs")
+ /// .with_content("fn main() {\n println!(\"I should be a Fibonacci!\");\n}")
+ /// .file("delete_me.rs")
+ /// .delete()
+ /// .send()
+ /// .await?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn update(&self, id: impl AsRef<str>) -> UpdateGistBuilder<'octo> {
+ UpdateGistBuilder::new(self.crab, format!("gists/{id}", id=id.as_ref()))
+ }
+
/// Get a single gist.
+ ///
/// ```no_run
/// # async fn run() -> octocrab::Result<()> {
/// let gist = octocrab::instance().gists().get("00000000000000000000000000000000").await?;
@@ -106,16 +131,19 @@ impl<'octo> CreateGistBuilder<'octo> {
}
}
+ /// Set a description for the gist to be created.
pub fn description(mut self, description: impl Into<String>) -> Self {
self.data.description = Some(description.into());
self
}
+ /// Set the `public` flag of the gist to be created.
pub fn public(mut self, public: bool) -> Self {
self.data.public = Some(public);
self
}
+ /// Add a file to the gist with `filename` and `content`.
pub fn file(mut self, filename: impl Into<String>, content: impl Into<String>) -> Self {
let file = CreateGistFile {
filename: Default::default(),
@@ -125,6 +153,7 @@ impl<'octo> CreateGistBuilder<'octo> {
self
}
+ /// Send the `CreateGist` request to Github for execution.
pub async fn send(self) -> Result<Gist> {
self.crab.post("gists", Some(&self.data)).await
}
@@ -145,3 +174,119 @@ struct CreateGistFile {
filename: Option<String>,
content: String,
}
+
+#[derive(Debug)]
+pub struct UpdateGistBuilder<'octo> {
+ crab: &'octo Octocrab,
+ gist_path: String,
+ data: UpdateGist
+}
+
+impl<'octo> UpdateGistBuilder<'octo> {
+ fn new(crab: &'octo Octocrab, gist_path: String) -> Self {
+ Self {
+ crab,
+ gist_path,
+ data: Default::default()
+ }
+ }
+
+ /// Update the description of the the gist with the content provided by `description`.
+ pub fn description(mut self, description: impl Into<String>) -> Self {
+ self.data.description = Some(description.into());
+ self
+ }
+
+ /// Update the file with the `filename`.
+ ///
+ /// The update operation is chosen in further calls to the returned builder.
+ pub fn file(self, filename: impl Into<String>) -> UpdateGistFileBuilder<'octo> {
+ UpdateGistFileBuilder::new(self, filename)
+ }
+
+ /// Send the `UpdateGist` command to Github for execution.
+ pub async fn send(self) -> Result<Gist> {
+ self.crab.patch(self.gist_path, Some(&self.data)).await
+ }
+}
+
+#[derive(Debug, Default, Serialize)]
+struct UpdateGist {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ description: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ files: Option<BTreeMap<String, Option<UpdateGistFile>>>
+}
+
+#[derive(Debug, Default, Serialize)]
+pub struct UpdateGistFile {
+ filename: Option<String>,
+ content: Option<String>
+}
+
+pub struct UpdateGistFileBuilder<'octo> {
+ builder: UpdateGistBuilder<'octo>,
+ filename: String,
+ file: Option<UpdateGistFile>,
+ ready: bool
+}
+
+impl<'octo> UpdateGistFileBuilder<'octo> {
+ fn new(builder: UpdateGistBuilder<'octo>, filename: impl Into<String>) -> Self {
+ Self {
+ builder,
+ filename: filename.into(),
+ file: None,
+ ready: false
+ }
+ }
+
+ fn build(mut self) -> UpdateGistBuilder<'octo> {
+ if self.ready {
+ self.builder.data.files.get_or_insert_with(BTreeMap::new).insert(self.filename, self.file);
+ }
+ self.builder
+ }
+
+ /// Delete the file from the gist.
+ pub fn delete(mut self) -> UpdateGistBuilder<'octo> {
+ self.ready = true;
+ self.file = None;
+ self.build()
+ }
+
+ /// Rename the file to `filename`.
+ pub fn rename_to(mut self, filename: impl Into<String>) -> Self {
+ self.ready = true;
+ self.file.get_or_insert_with(Default::default).filename = Some(filename.into());
+ self
+ }
+
+ /// Update the content of the file and overwrite it with `content`.
+ pub fn with_content(mut self, content: impl Into<String>) -> Self {
+ self.ready = true;
+ self.file.get_or_insert_with(Default::default).content = Some(content.into());
+ self
+ }
+
+ /// Overwrite the Description of the gist with `description`.
+ ///
+ /// This will finalize the update operation and will continue to operate on the gist itself.
+ pub fn description(self, description: impl Into<String>) -> UpdateGistBuilder<'octo> {
+ self.build().description(description)
+ }
+
+ /// Update the next file identified by `filename`.
+ ///
+ /// This will finalize the update operation and will continue to operate on the gist itself.
+ pub fn file(self, filename: impl Into<String>) -> UpdateGistFileBuilder<'octo> {
+ self.build().file(filename)
+ }
+
+ /// Send the `UpdateGist` command to Github for execution.
+ ///
+ /// This will finalize the update operation before sending.
+ pub async fn send(self) -> Result<Gist> {
+ self.build().send().await
+ }
+}