use serde::Deserialize;
use std::io::Cursor;
use tiny_http::Response;
use crate::handlers::{error_response, json_response, State};
pub(crate) fn branches_list_handler(state: &State) -> Response<Cursor<Vec<u8>>> {
let store = state.store.lock().unwrap();
let branches = match store.list_branches() {
Ok(b) => b,
Err(e) => return error_response(500, format!("list_branches: {e}")),
};
json_response(200, &serde_json::json!({
"branches": branches,
"current": store.current_branch(),
}))
}
#[derive(Deserialize)]
struct BranchCreateReq {
name: String,
#[serde(default)]
from: Option<String>,
#[serde(default)]
checkout: bool,
}
pub(crate) fn branch_create_handler(state: &State, body: &str) -> Response<Cursor<Vec<u8>>> {
let req: BranchCreateReq = match serde_json::from_str(body) {
Ok(r) => r, Err(e) => return error_response(400, format!("bad request: {e}")),
};
let store = state.store.lock().unwrap();
let from = req.from.unwrap_or_else(|| store.current_branch());
if from != lex_store::DEFAULT_BRANCH && matches!(store.get_branch(&from), Ok(None)) {
return error_response(404, format!("unknown source branch `{from}`"));
}
if let Err(e) = store.create_branch(&req.name, &from) {
return match e {
lex_store::StoreError::InvalidTransition(msg) => error_response(400, msg),
other => error_response(500, format!("create_branch: {other}")),
};
}
if req.checkout {
if let Err(e) = store.set_current_branch(&req.name) {
return error_response(500, format!("checkout after create: {e}"));
}
}
let head = store.get_branch(&req.name).ok().flatten().and_then(|b| b.head_op);
json_response(201, &serde_json::json!({
"name": req.name,
"from": from,
"head_op": head,
"current": store.current_branch(),
}))
}
pub(crate) fn branch_checkout_handler(state: &State, name: &str) -> Response<Cursor<Vec<u8>>> {
let store = state.store.lock().unwrap();
if let Err(e) = store.set_current_branch(name) {
return match e {
lex_store::StoreError::UnknownBranch(b) => error_response(404, format!("unknown branch `{b}`")),
other => error_response(500, format!("set_current_branch: {other}")),
};
}
let head = store.get_branch(name).ok().flatten().and_then(|b| b.head_op);
json_response(200, &serde_json::json!({
"current": name,
"head_op": head,
}))
}