feat: pull handler
- test simple pull ok Signed-off-by: Pakin <pakin.t@forth.co.th>
This commit is contained in:
parent
bb3e55eecb
commit
d19dab7561
1 changed files with 80 additions and 1 deletions
81
src/app.rs
81
src/app.rs
|
|
@ -661,7 +661,7 @@ async fn push_handler(State(state): State<AppState>) -> impl IntoResponse {
|
||||||
.map(|x| x.to_string())
|
.map(|x| x.to_string())
|
||||||
.unwrap_or("master".to_string());
|
.unwrap_or("master".to_string());
|
||||||
|
|
||||||
if let Err(e) = push(config, repo, remote_name, branch) {
|
if let Err(e) = push(config, repo, "origin", branch) {
|
||||||
return (
|
return (
|
||||||
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
Json(json!({"error": e.to_string()})),
|
Json(json!({"error": e.to_string()})),
|
||||||
|
|
@ -700,6 +700,84 @@ fn push(
|
||||||
Err("cannot lock repo".into())
|
Err("cannot lock repo".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn pull_handler(State(state): State<AppState>) -> impl IntoResponse {
|
||||||
|
let config = state.clone().get_all_configures();
|
||||||
|
let repo = state.repo.clone();
|
||||||
|
let remote_name = match state.get_config("GIT_REPO_REMOTE") {
|
||||||
|
Some(s) => s,
|
||||||
|
None => {
|
||||||
|
return (
|
||||||
|
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(json!({"error": "repo remote not existed"})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let branch = &config
|
||||||
|
.get("GIT_REPO_BRANCH_NAME")
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.unwrap_or("master".to_string());
|
||||||
|
|
||||||
|
if let Err(e) = pull(config, repo, "origin", branch) {
|
||||||
|
return (
|
||||||
|
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(json!({"error": e.to_string()})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
axum::http::StatusCode::OK,
|
||||||
|
Json(json!({"result": "pull completed"})),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull is fetch + merge
|
||||||
|
fn pull(
|
||||||
|
config: gcm::Configure,
|
||||||
|
repo: Arc<Mutex<Repository>>,
|
||||||
|
remote_name: &str,
|
||||||
|
branch: &str,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
if let Ok(rlock) = repo.try_lock() {
|
||||||
|
let mut rem = rlock.find_remote(remote_name)?;
|
||||||
|
let mut callback = RemoteCallbacks::new();
|
||||||
|
callback.credentials(|_url, _user, _allowed| {
|
||||||
|
Cred::userpass_plaintext(
|
||||||
|
config.get("GIT_REPO_USERNAME").unwrap_or(&"".to_string()),
|
||||||
|
config.get("GIT_REPO_PASSWORD").unwrap_or(&"".to_string()),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let mut fetch_options = FetchOptions::new();
|
||||||
|
fetch_options.remote_callbacks(callback);
|
||||||
|
fetch_options.download_tags(git2::AutotagOption::All);
|
||||||
|
|
||||||
|
info!("fetching from {}...", remote_name);
|
||||||
|
rem.fetch(&[branch], Some(&mut fetch_options), None)?;
|
||||||
|
|
||||||
|
// resolve fetch vs merge
|
||||||
|
let fetch_head = rlock.find_reference("FETCH_HEAD")?;
|
||||||
|
let fetch_commit = rlock.reference_to_annotated_commit(&fetch_head)?;
|
||||||
|
|
||||||
|
let analysis = rlock.merge_analysis(&[&fetch_commit])?;
|
||||||
|
if analysis.0.is_fast_forward() {
|
||||||
|
let refname = format!("refs/heads/{branch}");
|
||||||
|
let mut reference = rlock.find_reference(&refname)?;
|
||||||
|
reference.set_target(fetch_commit.id(), "Fast-Forward")?;
|
||||||
|
rlock.set_head(&refname)?;
|
||||||
|
rlock.checkout_head(Some(git2::build::CheckoutBuilder::default().force()))?;
|
||||||
|
info!("Fast-forwared to {}", fetch_commit.id());
|
||||||
|
} else if analysis.0.is_normal() {
|
||||||
|
warn!("need manual merge");
|
||||||
|
} else {
|
||||||
|
info!("already up to date");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Err("cannot lock repo".into())
|
||||||
|
}
|
||||||
|
|
||||||
/// Return git state & server state
|
/// Return git state & server state
|
||||||
async fn health_handler(State(_): State<AppState>) -> impl IntoResponse {
|
async fn health_handler(State(_): State<AppState>) -> impl IntoResponse {
|
||||||
(
|
(
|
||||||
|
|
@ -748,6 +826,7 @@ pub async fn run(config: gcm::Configure) -> gcm::StandardResult {
|
||||||
.route("/fetch", get(fetch_handler))
|
.route("/fetch", get(fetch_handler))
|
||||||
.route("/commit", post(commit_handler))
|
.route("/commit", post(commit_handler))
|
||||||
.route("/push", get(push_handler))
|
.route("/push", get(push_handler))
|
||||||
|
.route("/pull", get(pull_handler))
|
||||||
.route("/health", get(health_handler))
|
.route("/health", get(health_handler))
|
||||||
// .route("/healthz", get(reg::health))
|
// .route("/healthz", get(reg::health))
|
||||||
.with_state(state);
|
.with_state(state);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue