aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-06-24 07:35:47 +0200
committerMartin Fischer <martin@push-f.com>2021-06-24 07:38:48 +0200
commitb3e7c889b40a64db20bc52e579938d9c57f1bc3a (patch)
tree66b37051754493d58b1e4ec4b74ceb63691f9792
parent43b4b8693890a85f24eb358bc5545232ebf8e796 (diff)
refactor: split up blob routes into functions
-rw-r--r--src/get_routes.rs553
-rw-r--r--src/main.rs6
2 files changed, 305 insertions, 254 deletions
diff --git a/src/get_routes.rs b/src/get_routes.rs
index 01332e1..effc68a 100644
--- a/src/get_routes.rs
+++ b/src/get_routes.rs
@@ -23,296 +23,343 @@ use crate::Error;
use crate::Page;
use crate::Response;
-#[derive(Deserialize)]
-struct LogParam {
- commit: Option<String>,
-}
-
-pub(crate) fn view_blob<C: Controller>(
+pub(crate) fn get_blob<C: Controller>(
entr: TreeEntry,
params: ActionParam,
controller: &C,
ctx: Context,
) -> Result<Response, Error> {
- let filename = ctx.path.file_name().unwrap().to_str().unwrap();
-
match params.action.as_ref() {
- "view" => {
- let mut page = Page {
- title: filename.to_string(),
- body: String::new(),
- header: Some(action_links(&params.action, controller, &ctx)),
- controller,
- parts: &ctx.parts,
- };
-
- if let Some(access_info_html) = controller.access_info_html(&ctx) {
- page.body.push_str(&access_info_html);
- }
+ "view" => view_blob(entr, params, controller, ctx),
+ "edit" => edit_blob(entr, params, controller, ctx),
+ "upload" => Ok(forms::upload_form(true, controller, &ctx).into()),
+ "log" => log_blob(entr, params, controller, ctx),
+ "raw" => raw_blob(entr, params, controller, ctx),
+ "move" => move_blob(entr, params, controller, ctx),
+ "remove" => remove_blob(entr, params, controller, ctx),
+ _ => Err(Error::BadRequest("unknown action".into())),
+ }
+}
- if entr.filemode() == FileMode::Link.into() {
- // TODO: indicate and link symbolic link
- }
+fn view_blob<C: Controller>(
+ entr: TreeEntry,
+ params: ActionParam,
+ controller: &C,
+ ctx: Context,
+) -> Result<Response, Error> {
+ let mut page = Page {
+ title: ctx.file_name().unwrap().to_owned(),
+ body: String::new(),
+ header: Some(action_links(&params.action, controller, &ctx)),
+ controller,
+ parts: &ctx.parts,
+ };
- let blob = ctx.repo.find_blob(entr.id()).unwrap();
+ if let Some(access_info_html) = controller.access_info_html(&ctx) {
+ page.body.push_str(&access_info_html);
+ }
- if let Some(mime) = mime_guess::from_path(&ctx.path).first() {
- if mime.type_() == "image" {
- page.body
- .push_str("<div class=img-container><img src=?action=raw></div>");
- return Ok(page.into());
- }
- }
+ if entr.filemode() == FileMode::Link.into() {
+ // TODO: indicate and link symbolic link
+ }
- match from_utf8(blob.content()) {
- Ok(text) => {
- if let Some(renderer) = get_renderer(&ctx.path) {
- page.body.push_str(&renderer(text));
- } else {
- page.body
- .push_str(&format!("<pre>{}</pre>", html_escape(text)));
- }
- }
- Err(_) => page.body.push_str("failed to decode file as UTF-8"),
- }
+ let blob = ctx.repo.find_blob(entr.id()).unwrap();
- Ok(page.into())
+ if let Some(mime) = mime_guess::from_path(&ctx.path).first() {
+ if mime.type_() == "image" {
+ page.body
+ .push_str("<div class=img-container><img src=?action=raw></div>");
+ return Ok(page.into());
}
- "edit" => {
- if !controller.may_write_path(&ctx) {
- return Err(Error::Unauthorized(
- "you are not authorized to edit this file".into(),
- ctx,
- ));
- }
- let blob = ctx.repo.find_blob(entr.id()).unwrap();
- if let Ok(text) = from_utf8(blob.content()) {
- return Ok(forms::edit_text_form(
- &forms::EditForm {
- text: text.to_string(),
- oid: Some(entr.id().to_string()),
- ..Default::default()
- },
- None,
- controller,
- &ctx,
- )
- .into());
+ }
+
+ match from_utf8(blob.content()) {
+ Ok(text) => {
+ if let Some(renderer) = get_renderer(&ctx.path) {
+ page.body.push_str(&renderer(text));
} else {
- return Ok(forms::upload_form(true, controller, &ctx).into());
+ page.body
+ .push_str(&format!("<pre>{}</pre>", html_escape(text)));
}
}
- "upload" => {
- return Ok(forms::upload_form(true, controller, &ctx).into());
+ Err(_) => page.body.push_str("failed to decode file as UTF-8"),
+ }
+
+ Ok(page.into())
+}
+
+fn edit_blob<C: Controller>(
+ entr: TreeEntry,
+ _params: ActionParam,
+ controller: &C,
+ ctx: Context,
+) -> Result<Response, Error> {
+ if !controller.may_write_path(&ctx) {
+ return Err(Error::Unauthorized(
+ "you are not authorized to edit this file".into(),
+ ctx,
+ ));
+ }
+ let blob = ctx.repo.find_blob(entr.id()).unwrap();
+ if let Ok(text) = from_utf8(blob.content()) {
+ return Ok(forms::edit_text_form(
+ &forms::EditForm {
+ text: text.to_string(),
+ oid: Some(entr.id().to_string()),
+ ..Default::default()
+ },
+ None,
+ controller,
+ &ctx,
+ )
+ .into());
+ } else {
+ return Ok(forms::upload_form(true, controller, &ctx).into());
+ }
+}
+
+#[derive(Deserialize)]
+struct LogParam {
+ commit: Option<String>,
+}
+
+fn log_blob<C: Controller>(
+ _entr: TreeEntry,
+ params: ActionParam,
+ controller: &C,
+ ctx: Context,
+) -> Result<Response, Error> {
+ let log_param: LogParam = ctx.parts.query().unwrap();
+
+ let filename = ctx.file_name().unwrap();
+
+ // TODO: move to separate function
+ if let Some(commit) = log_param.commit {
+ let branch_commit = ctx.branch_head()?;
+
+ let commit = ctx
+ .repo
+ .find_commit(Oid::from_str(&commit)?)
+ .map_err(|_| Error::NotFound("commit not found".into()))?;
+
+ if branch_commit.id() != commit.id()
+ && !ctx
+ .repo
+ .graph_descendant_of(branch_commit.id(), commit.id())?
+ {
+ // disallow viewing commits from other branches you shouldn't have access to
+ return Err(Error::NotFound("commit not found".into()));
}
- "log" => {
- let log_param: LogParam = ctx.parts.query().unwrap();
-
- if let Some(commit) = log_param.commit {
- let branch_commit = ctx.branch_head()?;
-
- let commit = ctx
- .repo
- .find_commit(Oid::from_str(&commit)?)
- .map_err(|_| Error::NotFound("commit not found".into()))?;
-
- if branch_commit.id() != commit.id()
- && !ctx
- .repo
- .graph_descendant_of(branch_commit.id(), commit.id())?
- {
- // disallow viewing commits from other branches you shouldn't have access to
- return Err(Error::NotFound("commit not found".into()));
- }
- let blob_id = if let Ok(entry) = commit.tree()?.get_path(&ctx.path) {
- entry.id()
- } else {
- return Ok(Page {
- title: format!("Commit for {}", filename),
- body: "file removed".into(),
- header: Some(action_links(&params.action, controller, &ctx)),
- controller,
- parts: &ctx.parts,
- }
- .into());
- };
-
- // TODO: if UTF-8 decoding fails, link ?action=raw&rev=
- // TODO: what if there are multiple parents?
- let old_blob_id = commit
- .parents()
- .next()
- .and_then(|p| p.tree().unwrap().get_path(&ctx.path).ok())
- .map(|e| e.id());
- if Some(blob_id) != old_blob_id {
- let mut page = Page {
- title: format!("Commit for {}", filename),
- header: Some(action_links(&params.action, controller, &ctx)),
- body: format!(
- "<h1>{}</h1>{} committed on {}",
- html_escape(commit.summary().unwrap_or_default()),
- html_escape(commit.author().name().unwrap_or_default()),
- NaiveDateTime::from_timestamp(commit.time().seconds(), 0)
- .format("%b %d, %Y, %H:%M")
- ),
- controller,
- parts: &ctx.parts,
- };
- if let Some(old_blob_id) = old_blob_id {
- page.body.push_str(&diff(
- from_utf8(ctx.repo.find_blob(old_blob_id)?.content())?,
- from_utf8(ctx.repo.find_blob(blob_id)?.content())?,
- ))
- } else {
- page.body.push_str(&diff(
- "",
- from_utf8(&ctx.repo.find_blob(blob_id)?.content())?,
- ));
- }
- return Ok(page.into());
- } else {
- return Err(Error::NotFound("commit not found".into()));
- }
+ let blob_id = if let Ok(entry) = commit.tree()?.get_path(&ctx.path) {
+ entry.id()
+ } else {
+ return Ok(Page {
+ title: format!("Commit for {}", filename),
+ body: "file removed".into(),
+ header: Some(action_links(&params.action, controller, &ctx)),
+ controller,
+ parts: &ctx.parts,
}
+ .into());
+ };
+ // TODO: if UTF-8 decoding fails, link ?action=raw&rev=
+ // TODO: what if there are multiple parents?
+ let old_blob_id = commit
+ .parents()
+ .next()
+ .and_then(|p| p.tree().unwrap().get_path(&ctx.path).ok())
+ .map(|e| e.id());
+ if Some(blob_id) != old_blob_id {
let mut page = Page {
- title: format!("Log for {}", filename),
- body: String::new(),
+ title: format!("Commit for {}", filename),
header: Some(action_links(&params.action, controller, &ctx)),
+ body: format!(
+ "<h1>{}</h1>{} committed on {}",
+ html_escape(commit.summary().unwrap_or_default()),
+ html_escape(commit.author().name().unwrap_or_default()),
+ NaiveDateTime::from_timestamp(commit.time().seconds(), 0)
+ .format("%b %d, %Y, %H:%M")
+ ),
controller,
parts: &ctx.parts,
};
-
- let mut walk = ctx.repo.revwalk()?;
- let branch_head = ctx.branch_head()?;
- walk.push(branch_head.id())?;
-
- let mut prev_commit = branch_head;
- let mut prev_blobid = Some(prev_commit.tree()?.get_path(&ctx.path)?.id());
-
- let mut commits = Vec::new();
-
- // TODO: paginate
- for oid in walk.flatten().skip(1) {
- let commit = ctx.repo.find_commit(oid)?;
- if let Ok(entr) = commit.tree()?.get_path(&ctx.path) {
- let blobid = entr.id();
- if Some(blobid) != prev_blobid {
- commits.push(prev_commit);
- prev_blobid = Some(blobid);
- }
- prev_commit = commit;
- } else {
- if prev_blobid.is_some() {
- commits.push(prev_commit);
- }
- prev_commit = commit;
- prev_blobid = None;
- }
+ if let Some(old_blob_id) = old_blob_id {
+ page.body.push_str(&diff(
+ from_utf8(ctx.repo.find_blob(old_blob_id)?.content())?,
+ from_utf8(ctx.repo.find_blob(blob_id)?.content())?,
+ ))
+ } else {
+ page.body.push_str(&diff(
+ "",
+ from_utf8(&ctx.repo.find_blob(blob_id)?.content())?,
+ ));
}
- if prev_commit.parent_count() == 0 && prev_commit.tree()?.get_path(&ctx.path).is_ok() {
- // the very first commit of the branch
+ return Ok(page.into());
+ } else {
+ return Err(Error::NotFound("commit not found".into()));
+ }
+ }
+
+ let mut page = Page {
+ title: format!("Log for {}", filename),
+ body: String::new(),
+ header: Some(action_links(&params.action, controller, &ctx)),
+ controller,
+ parts: &ctx.parts,
+ };
+
+ let mut walk = ctx.repo.revwalk()?;
+ let branch_head = ctx.branch_head()?;
+ walk.push(branch_head.id())?;
+
+ let mut prev_commit = branch_head;
+ let mut prev_blobid = Some(prev_commit.tree()?.get_path(&ctx.path)?.id());
+
+ let mut commits = Vec::new();
+
+ // TODO: paginate
+ for oid in walk.flatten().skip(1) {
+ let commit = ctx.repo.find_commit(oid)?;
+ if let Ok(entr) = commit.tree()?.get_path(&ctx.path) {
+ let blobid = entr.id();
+ if Some(blobid) != prev_blobid {
commits.push(prev_commit);
+ prev_blobid = Some(blobid);
}
- let mut prev_date = None;
- for c in commits {
- let date = NaiveDateTime::from_timestamp(c.time().seconds(), 0).date();
- if Some(date) != prev_date {
- if prev_date != None {
- page.body.push_str("</ul>");
- }
- page.body
- .push_str(&format!("{}<ul>", date.format("%b %d, %Y")));
- }
-
- page.body.push_str(&format!(
- "<li><a href='?action=log&commit={}'>{}: {}</a></li>",
- html_escape(c.id().to_string()),
- html_escape(c.author().name().unwrap_or_default()),
- html_escape(c.summary().unwrap_or_default()),
- ));
- prev_date = Some(date);
+ prev_commit = commit;
+ } else {
+ if prev_blobid.is_some() {
+ commits.push(prev_commit);
}
- page.body.push_str("</ul>");
- Ok(page.into())
+ prev_commit = commit;
+ prev_blobid = None;
}
- "raw" => {
- if let Some(etag) = ctx
- .parts
- .headers
- .get(header::IF_NONE_MATCH)
- .and_then(|v| v.to_str().ok())
- {
- if etag.trim_matches('"') == entr.id().to_string() {
- return Ok(Builder::new()
- .status(StatusCode::NOT_MODIFIED)
- .body("".into())
- .unwrap());
- }
+ }
+ if prev_commit.parent_count() == 0 && prev_commit.tree()?.get_path(&ctx.path).is_ok() {
+ // the very first commit of the branch
+ commits.push(prev_commit);
+ }
+ let mut prev_date = None;
+ for c in commits {
+ let date = NaiveDateTime::from_timestamp(c.time().seconds(), 0).date();
+ if Some(date) != prev_date {
+ if prev_date != None {
+ page.body.push_str("</ul>");
}
+ page.body
+ .push_str(&format!("{}<ul>", date.format("%b %d, %Y")));
+ }
+
+ page.body.push_str(&format!(
+ "<li><a href='?action=log&commit={}'>{}: {}</a></li>",
+ html_escape(c.id().to_string()),
+ html_escape(c.author().name().unwrap_or_default()),
+ html_escape(c.summary().unwrap_or_default()),
+ ));
+ prev_date = Some(date);
+ }
+ page.body.push_str("</ul>");
+ Ok(page.into())
+}
- let blob = ctx.repo.find_blob(entr.id()).unwrap();
- let mut resp = Response::new(blob.content().to_owned().into());
+fn raw_blob<C: Controller>(
+ entr: TreeEntry,
+ _params: ActionParam,
+ _controller: &C,
+ ctx: Context,
+) -> Result<Response, Error> {
+ if let Some(etag) = ctx
+ .parts
+ .headers
+ .get(header::IF_NONE_MATCH)
+ .and_then(|v| v.to_str().ok())
+ {
+ if etag.trim_matches('"') == entr.id().to_string() {
+ return Ok(Builder::new()
+ .status(StatusCode::NOT_MODIFIED)
+ .body("".into())
+ .unwrap());
+ }
+ }
+ let blob = ctx.repo.find_blob(entr.id()).unwrap();
+ let mut resp = Response::new(blob.content().to_owned().into());
+
+ resp.headers_mut()
+ .insert(header::ETAG, format!("\"{}\"", entr.id()).parse().unwrap());
+ resp.headers_mut()
+ .insert(header::CACHE_CONTROL, "no-cache".parse().unwrap());
+
+ if let Some(mime) = mime_guess::from_path(&ctx.path).first() {
+ if mime.type_() == "text" {
+ // workaround for Firefox, which downloads non-plain text subtypes
+ // instead of displaying them (https://bugzilla.mozilla.org/1319262)
resp.headers_mut()
- .insert(header::ETAG, format!("\"{}\"", entr.id()).parse().unwrap());
+ .insert(header::CONTENT_TYPE, "text/plain".parse().unwrap());
+ } else {
resp.headers_mut()
- .insert(header::CACHE_CONTROL, "no-cache".parse().unwrap());
-
- if let Some(mime) = mime_guess::from_path(&ctx.path).first() {
- if mime.type_() == "text" {
- // workaround for Firefox, which downloads non-plain text subtypes
- // instead of displaying them (https://bugzilla.mozilla.org/1319262)
- resp.headers_mut()
- .insert(header::CONTENT_TYPE, "text/plain".parse().unwrap());
- } else {
- resp.headers_mut()
- .insert(header::CONTENT_TYPE, mime.to_string().parse().unwrap());
- }
- }
- Ok(resp)
- }
- "move" => {
- if !controller.may_move_path(&ctx) {
- return Err(Error::Unauthorized(
- "you are not authorized to move this file".into(),
- ctx,
- ));
- }
- return forms::move_form(
- filename,
- &forms::MoveForm {
- dest: ctx.path.to_str().unwrap().to_owned(),
- msg: None,
- },
- None,
- controller,
- &ctx,
- );
+ .insert(header::CONTENT_TYPE, mime.to_string().parse().unwrap());
}
- "remove" => {
- if !controller.may_move_path(&ctx) {
- return Err(Error::Unauthorized(
- "you are not authorized to remove this file".into(),
- ctx,
- ));
- }
- let page = Page {
- title: format!("Remove {}", filename),
- controller,
- parts: &ctx.parts,
- header: Some(action_links(&params.action, controller, &ctx)),
- body: "<form method=post autocomplete=off>\
- <label>Message <input name=msg autofocus></label>\
- <button>Remove</button></form>"
- .into(),
- };
+ }
+ Ok(resp)
+}
- Ok(page.into())
- }
- _ => Err(Error::BadRequest("unknown action".into())),
+fn move_blob<C: Controller>(
+ _entr: TreeEntry,
+ _params: ActionParam,
+ controller: &C,
+ ctx: Context,
+) -> Result<Response, Error> {
+ if !controller.may_move_path(&ctx) {
+ return Err(Error::Unauthorized(
+ "you are not authorized to move this file".into(),
+ ctx,
+ ));
}
+
+ let filename = ctx.file_name().unwrap();
+
+ return forms::move_form(
+ filename,
+ &forms::MoveForm {
+ dest: ctx.path.to_str().unwrap().to_owned(),
+ msg: None,
+ },
+ None,
+ controller,
+ &ctx,
+ );
+}
+
+fn remove_blob<C: Controller>(
+ entr: TreeEntry,
+ params: ActionParam,
+ controller: &C,
+ ctx: Context,
+) -> Result<Response, Error> {
+ if !controller.may_move_path(&ctx) {
+ return Err(Error::Unauthorized(
+ "you are not authorized to remove this file".into(),
+ ctx,
+ ));
+ }
+
+ let filename = ctx.file_name().unwrap();
+
+ let page = Page {
+ title: format!("Remove {}", filename),
+ controller,
+ parts: &ctx.parts,
+ header: Some(action_links(&params.action, controller, &ctx)),
+ body: "<form method=post autocomplete=off>\
+ <label>Message <input name=msg autofocus></label>\
+ <button>Remove</button></form>"
+ .into(),
+ };
+
+ Ok(page.into())
}
pub fn view_tree<C: Controller>(
diff --git a/src/main.rs b/src/main.rs
index 30f018b..fc0b7ce 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -442,7 +442,7 @@ async fn build_response<C: Controller>(
.body("redirecting".into())
.unwrap());
}
- return get_routes::view_blob(entr, params, controller, ctx);
+ return get_routes::get_blob(entr, params, controller, ctx);
}
tree = ctx.repo.find_tree(entr.id());
@@ -528,6 +528,10 @@ impl Context {
parent_commits,
)
}
+
+ fn file_name(&self) -> Option<&str> {
+ self.path.file_name().and_then(|x| x.to_str())
+ }
}
fn render_markdown(input: &str) -> String {