mirror of
https://github.com/Lumither/nocturne.git
synced 2026-10-17 10:26:21 +00:00
feat(blog::components::check+update) update
This commit is contained in:
17 files changed
+229
-81
No files matched your search
@@ -1,3 +1,5 @@
|
|||||||
|
// todo: rebuild with static OnceCell
|
||||||
|
|
||||||
// Database related
|
// Database related
|
||||||
pub mod database {
|
pub mod database {
|
||||||
pub mod var_name {
|
pub mod var_name {
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
SELECT
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
use macros::dev_consume;
|
use macros::dev_consume;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
|
Json,
|
||||||
extract::{Path, State},
|
extract::{Path, State},
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
Json,
|
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
use git2::Delta;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Change {
|
||||||
|
DELETE {
|
||||||
|
uuid: Uuid,
|
||||||
|
},
|
||||||
|
RENAME {
|
||||||
|
uuid: Uuid,
|
||||||
|
from: PathBuf,
|
||||||
|
to: PathBuf,
|
||||||
|
},
|
||||||
|
UPDATE {
|
||||||
|
uuid: Uuid,
|
||||||
|
content: String,
|
||||||
|
},
|
||||||
|
CREATE {
|
||||||
|
uuid: Uuid,
|
||||||
|
path: PathBuf,
|
||||||
|
content: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct DeltaIdx {
|
||||||
|
pub delta_type: Delta,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum PostIdxError {
|
pub enum Error {
|
||||||
#[error("missing essential field `{}` for file `{}`", field, filename)]
|
#[error("missing essential field `{}` for file `{}`", field, filename)]
|
||||||
MissingField { field: String, filename: String },
|
MissingField { field: String, filename: String },
|
||||||
|
|
||||||
@@ -46,4 +46,7 @@ pub enum PostIdxError {
|
|||||||
id: String,
|
id: String,
|
||||||
msg: String,
|
msg: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[error("git error")]
|
||||||
|
Git2(#[from] git2::Error),
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::modules::blog::components::check_update::pull::{analyze_deltas, fetch_deltas};
|
||||||
use crate::modules::blog::components::check_update::{
|
use crate::modules::blog::components::check_update::{
|
||||||
// index::drop_index,
|
// index::drop_index,
|
||||||
// utils::{expand_path, index_files, search_md},
|
// utils::{expand_path, index_files, search_md},
|
||||||
@@ -13,14 +14,18 @@ use crate::modules::blog::components::check_update::{
|
|||||||
};
|
};
|
||||||
use crate::scheduler::task_func::AsyncTaskFunc;
|
use crate::scheduler::task_func::AsyncTaskFunc;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use tracing::{info, warn, Level};
|
use tracing::{info, trace, warn, Level};
|
||||||
|
|
||||||
// mod error;
|
// mod error;
|
||||||
// mod index;
|
// mod index;
|
||||||
|
mod changes;
|
||||||
|
mod error;
|
||||||
|
mod pull;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Args {
|
struct Args {
|
||||||
|
db_connection: PgPool,
|
||||||
git_work_dir: PathBuf,
|
git_work_dir: PathBuf,
|
||||||
git_url: String,
|
git_url: String,
|
||||||
git_remote_name: String,
|
git_remote_name: String,
|
||||||
@@ -45,7 +50,6 @@ pub fn task(db_connection: PgPool) -> impl AsyncTaskFunc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// clone & check update
|
// clone & check update
|
||||||
|
|
||||||
let git_url = match env::var(var_name::BLOG_GIT_URL) {
|
let git_url = match env::var(var_name::BLOG_GIT_URL) {
|
||||||
Ok(url) => url,
|
Ok(url) => url,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -63,16 +67,33 @@ pub fn task(db_connection: PgPool) -> impl AsyncTaskFunc {
|
|||||||
.unwrap_or(default_value::BLOG_GIT_REMOTE_BRANCH.to_string());
|
.unwrap_or(default_value::BLOG_GIT_REMOTE_BRANCH.to_string());
|
||||||
|
|
||||||
let arc_args = Arc::new(Args {
|
let arc_args = Arc::new(Args {
|
||||||
|
db_connection,
|
||||||
git_work_dir,
|
git_work_dir,
|
||||||
git_url,
|
git_url,
|
||||||
git_remote_name,
|
git_remote_name,
|
||||||
git_remote_branch,
|
git_remote_branch,
|
||||||
});
|
});
|
||||||
|
|
||||||
move || Box::pin(test(arc_args.clone()))
|
move || Box::pin(workflow(arc_args.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn test(args: Arc<Args>) {
|
async fn workflow(args: Arc<Args>) {
|
||||||
info!("test");
|
let deltas = match fetch_deltas(
|
||||||
dbg!(&args);
|
&args.git_url,
|
||||||
|
&args.git_remote_name,
|
||||||
|
&args.git_remote_branch,
|
||||||
|
&args.git_work_dir,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(updates) => updates,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
if deltas.is_empty() {
|
||||||
|
trace!("blog git already up-to-date");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let updates = analyze_deltas(deltas, &args.git_work_dir).await;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
use crate::modules::blog::components::check_update::changes::{Change, DeltaIdx};
|
||||||
|
use crate::modules::blog::components::check_update::error::Error;
|
||||||
|
use crate::utils::git;
|
||||||
|
use crate::utils::git::FileDelta;
|
||||||
|
use git2::{Delta, Repository};
|
||||||
|
use markdown::MdFile;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use tracing::error;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub async fn fetch_deltas(
|
||||||
|
git_url: &str,
|
||||||
|
git_remote_name: &str,
|
||||||
|
git_branch: &str,
|
||||||
|
git_work_dir: &PathBuf,
|
||||||
|
) -> Result<Vec<FileDelta>, Error> {
|
||||||
|
let repo = match Repository::open(git_work_dir) {
|
||||||
|
Ok(repo) => repo,
|
||||||
|
Err(_) => match Repository::clone(git_url, git_work_dir) {
|
||||||
|
Ok(repo) => repo,
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to clone blog content git({}): {}", &git_url, e);
|
||||||
|
return Err(e.into());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let updates = match git::sync(git_remote_name, git_branch, &repo) {
|
||||||
|
Ok(updates) => updates,
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
"failed to sync blog content git({}) updates: {}",
|
||||||
|
&git_url, e
|
||||||
|
);
|
||||||
|
return Err(e.into());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(updates)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn analyze_deltas(file_deltas: Vec<FileDelta>, git_work_dir: &Path) -> Vec<Change> {
|
||||||
|
dbg!(&file_deltas);
|
||||||
|
let mut changes: Vec<Change> = vec![];
|
||||||
|
let mut merge_deltas: Vec<FileDelta> = vec![];
|
||||||
|
|
||||||
|
for delta in file_deltas.into_iter() {
|
||||||
|
if delta.status == Delta::Modified {
|
||||||
|
let file_path = &git_work_dir.join(
|
||||||
|
delta
|
||||||
|
.new_path
|
||||||
|
.expect("cannot parse modified post `new_path`"),
|
||||||
|
);
|
||||||
|
let post = match MdFile::from_file(file_path) {
|
||||||
|
Ok(post) => post,
|
||||||
|
Err(e) => {
|
||||||
|
error!("md file parsing error: {}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = match extract_post_id(&post) {
|
||||||
|
Some(id) => id,
|
||||||
|
None => {
|
||||||
|
// todo: add to unresolved error list
|
||||||
|
error!(
|
||||||
|
"failed to parse uuid on post {}",
|
||||||
|
file_path.to_string_lossy()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
changes.push(Change::UPDATE {
|
||||||
|
uuid: id,
|
||||||
|
content: post.content,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
merge_deltas.push(delta)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge some addition and remove deltas to rename/move changes
|
||||||
|
let delta_idx = {
|
||||||
|
let mut delta_idx: HashMap<Uuid, Vec<DeltaIdx>> = HashMap::new();
|
||||||
|
for file_delta in merge_deltas.into_iter() {
|
||||||
|
let file_path = &git_work_dir.join(
|
||||||
|
file_delta
|
||||||
|
.new_path
|
||||||
|
.expect("cannot parse modified post `new_path`"),
|
||||||
|
);
|
||||||
|
match file_delta.status {
|
||||||
|
// todo: split impl
|
||||||
|
Delta::Added | Delta::Deleted => {
|
||||||
|
let file_path_str = file_path.to_string_lossy();
|
||||||
|
|
||||||
|
let post = match MdFile::from_file(file_path) {
|
||||||
|
Ok(post) => post,
|
||||||
|
Err(e) => {
|
||||||
|
error!("md file parsing error ({}): {}", file_path_str, e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = match extract_post_id(&post) {
|
||||||
|
Some(id) => id,
|
||||||
|
None => {
|
||||||
|
// todo: add to unresolved error list
|
||||||
|
error!("failed to parse uuid on post {}", file_path_str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let file_delta_idx = DeltaIdx {
|
||||||
|
delta_type: file_delta.status,
|
||||||
|
content: post.content,
|
||||||
|
};
|
||||||
|
delta_idx
|
||||||
|
.entry(id)
|
||||||
|
// todo: change to shallow copy
|
||||||
|
.and_modify(|v| v.push(file_delta_idx.clone()))
|
||||||
|
.or_insert(vec![file_delta_idx]);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!("unsupported delta on file {}", file_path.to_string_lossy());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
delta_idx
|
||||||
|
};
|
||||||
|
|
||||||
|
dbg!(&delta_idx);
|
||||||
|
|
||||||
|
changes
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_post_id(post: &MdFile) -> Option<Uuid> {
|
||||||
|
match post.meta["uuid"].as_str() {
|
||||||
|
Some(id) => match Uuid::parse_str(id) {
|
||||||
|
Ok(id) => Some(id),
|
||||||
|
Err(_) => None,
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,48 +8,6 @@ use chrono::{DateTime, FixedOffset, ParseResult};
|
|||||||
use dirs::home_dir;
|
use dirs::home_dir;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
// pub fn search_md(entry: PathBuf) -> Vec<PathBuf> {
|
|
||||||
// if entry.ends_with(".git") {
|
|
||||||
// return vec![];
|
|
||||||
// }
|
|
||||||
// if entry.is_dir() {
|
|
||||||
// if let Ok(files) = entry.read_dir() {
|
|
||||||
// files
|
|
||||||
// .flat_map(|file| {
|
|
||||||
// let file_path = file.unwrap().path();
|
|
||||||
// search_md(file_path)
|
|
||||||
// })
|
|
||||||
// .collect()
|
|
||||||
// } else {
|
|
||||||
// vec![]
|
|
||||||
// }
|
|
||||||
// } else if entry.extension().is_some_and(|ext| ext == "md") {
|
|
||||||
// vec![entry]
|
|
||||||
// } else {
|
|
||||||
// vec![]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn index_files(files: &[PathBuf], db_conn: &Pool<Postgres>) {
|
|
||||||
// let rt = Runtime::new().unwrap();
|
|
||||||
// rt.block_on(async {
|
|
||||||
// let files_clone = files.to_owned();
|
|
||||||
// let handlers = files_clone
|
|
||||||
// .into_iter()
|
|
||||||
// .map(|file: PathBuf| {
|
|
||||||
// let conn_clone = db_conn.clone();
|
|
||||||
// spawn(async move {
|
|
||||||
// if let Err(e) = index_file(&file, &conn_clone).await {
|
|
||||||
// error!("failed to index markdown file `{}`: {}", file.display(), e);
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// .collect::<Vec<_>>();
|
|
||||||
//
|
|
||||||
// block_on(join_all(handlers));
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn expand_path(path: String) -> String {
|
pub fn expand_path(path: String) -> String {
|
||||||
if path.starts_with('~') {
|
if path.starts_with('~') {
|
||||||
home_dir()
|
home_dir()
|
||||||
@@ -75,7 +33,3 @@ pub fn expand_path(path: String) -> String {
|
|||||||
pub fn parse_date(date_str: &str) -> ParseResult<DateTime<FixedOffset>> {
|
pub fn parse_date(date_str: &str) -> ParseResult<DateTime<FixedOffset>> {
|
||||||
DateTime::parse_from_str(format!("{}T120000", date_str).as_str(), DEFAULT_DATE_FORMAT)
|
DateTime::parse_from_str(format!("{}T120000", date_str).as_str(), DEFAULT_DATE_FORMAT)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn get_md_file_basename(f_name: &str) -> String {
|
|
||||||
// f_name.replace(".md", "")
|
|
||||||
// }
|
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
pub mod check_update;
|
pub mod check_update;
|
||||||
|
mod consistency_guard;
|
||||||
mod rag;
|
mod rag;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
mod api;
|
mod api;
|
||||||
mod components;
|
mod components;
|
||||||
|
|
||||||
|
use crate::modules::blog::components::check_update;
|
||||||
|
use crate::scheduler::tasks::async_basic::AsyncBasic;
|
||||||
use crate::{
|
use crate::{
|
||||||
modules::{
|
modules::{
|
||||||
blog::{
|
blog::{
|
||||||
@@ -16,9 +18,6 @@ use crate::{
|
|||||||
scheduler::tasks::CronTask,
|
scheduler::tasks::CronTask,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::modules::blog::components::check_update;
|
|
||||||
use crate::scheduler::tasks::async_basic::AsyncBasic;
|
|
||||||
use crate::scheduler::tasks::basic::BasicTask;
|
|
||||||
use axum::{routing::get, Router};
|
use axum::{routing::get, Router};
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
@@ -46,19 +45,11 @@ impl Module for Blog {
|
|||||||
|
|
||||||
fn get_cron_tasks(&self) -> Vec<(&str, Box<dyn CronTask>)> {
|
fn get_cron_tasks(&self) -> Vec<(&str, Box<dyn CronTask>)> {
|
||||||
let db_handler = self.db_handler.clone();
|
let db_handler = self.db_handler.clone();
|
||||||
vec![
|
vec![(
|
||||||
(
|
|
||||||
"Blog Check Update",
|
"Blog Check Update",
|
||||||
AsyncBasic::new(check_update::task(db_handler.clone()), "* * * * * *")
|
AsyncBasic::new(check_update::task(db_handler.clone()), "*/5 * * * * *")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_task(),
|
.to_task(),
|
||||||
),
|
)]
|
||||||
(
|
|
||||||
"Sync test task",
|
|
||||||
BasicTask::new(|| println!("test lol"), "* * * * * *")
|
|
||||||
.unwrap()
|
|
||||||
.to_task(),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,20 +2,20 @@ CREATE TABLE tags
|
|||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
name VARCHAR(20) UNIQUE NOT NULL,
|
name VARCHAR(20) UNIQUE NOT NULL,
|
||||||
description TEXT
|
description TEXT DEFAULT ''
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE categories
|
CREATE TABLE categories
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
name VARCHAR(20) UNIQUE NOT NULL,
|
name VARCHAR(20) UNIQUE NOT NULL,
|
||||||
description TEXT
|
description TEXT DEFAULT ''
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE posts
|
CREATE TABLE posts
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id UUID UNIQUE NOT NULL,
|
||||||
identifier VARCHAR(50) UNIQUE NOT NULL,
|
identifier VARCHAR(100) UNIQUE NOT NULL,
|
||||||
title VARCHAR(255) NOT NULL,
|
title VARCHAR(255) NOT NULL,
|
||||||
subtitle VARCHAR(255) NOT NULL,
|
subtitle VARCHAR(255) NOT NULL,
|
||||||
published_date DATE NOT NULL,
|
published_date DATE NOT NULL,
|
||||||
@@ -27,13 +27,13 @@ CREATE TABLE posts
|
|||||||
|
|
||||||
CREATE TABLE post_tag
|
CREATE TABLE post_tag
|
||||||
(
|
(
|
||||||
post SERIAL REFERENCES posts (id),
|
post UUID REFERENCES posts (id),
|
||||||
tag SERIAL REFERENCES tags (id)
|
tag SERIAL REFERENCES tags (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE metadata
|
CREATE TABLE metadata
|
||||||
(
|
(
|
||||||
pid SERIAL REFERENCES posts (id) NOT NULL,
|
pid UUID REFERENCES posts (id) NOT NULL,
|
||||||
meta_key VARCHAR(50) NOT NULL,
|
meta_key VARCHAR(50) NOT NULL,
|
||||||
meta_value TEXT NOT NULL,
|
meta_value TEXT NOT NULL,
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::{env, num::ParseIntError};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::config::server::{default_value, var_name},
|
constants::config::server::{default_value, var_name},
|
||||||
scheduler::{tasks::CronTask, Scheduler},
|
scheduler::{Scheduler, tasks::CronTask},
|
||||||
};
|
};
|
||||||
use macros::error_panic;
|
use macros::error_panic;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ pub struct Scheduler {
|
|||||||
impl Scheduler {
|
impl Scheduler {
|
||||||
/// Start all tasks in the scheduler
|
/// Start all tasks in the scheduler
|
||||||
pub async fn start(&self) {
|
pub async fn start(&self) {
|
||||||
dbg!("entering");
|
|
||||||
|
|
||||||
let fut = self
|
let fut = self
|
||||||
.task_pool
|
.task_pool
|
||||||
.clone()
|
.clone()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::{sync::Arc, time::Duration};
|
|||||||
use crate::scheduler::{error::SchedulerError, tasks::CronTask};
|
use crate::scheduler::{error::SchedulerError, tasks::CronTask};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use tokio::time::{sleep, Sleep};
|
use tokio::time::{Sleep, sleep};
|
||||||
|
|
||||||
pub fn duration_from_now(future: DateTime<Utc>) -> Duration {
|
pub fn duration_from_now(future: DateTime<Utc>) -> Duration {
|
||||||
future
|
future
|
||||||
|
|||||||
@@ -3,12 +3,11 @@
|
|||||||
/// https://github.com/rust-lang/git2-rs/commit/f3b87baed1e33d6c2d94fe1fa6aa6503a071d837
|
/// https://github.com/rust-lang/git2-rs/commit/f3b87baed1e33d6c2d94fe1fa6aa6503a071d837
|
||||||
///
|
///
|
||||||
use git2::{
|
use git2::{
|
||||||
build, AnnotatedCommit, AutotagOption, Delta, FetchOptions, Reference, Remote, Repository,
|
AnnotatedCommit, AutotagOption, Delta, FetchOptions, Reference, Remote, Repository, build,
|
||||||
};
|
};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub struct FileDelta {
|
pub struct FileDelta {
|
||||||
pub old_path: Option<PathBuf>,
|
pub old_path: Option<PathBuf>,
|
||||||
@@ -40,7 +39,6 @@ fn fast_forward(
|
|||||||
None => String::from_utf8_lossy(lb.name_bytes()).to_string(),
|
None => String::from_utf8_lossy(lb.name_bytes()).to_string(),
|
||||||
};
|
};
|
||||||
let msg = format!("fast-forward({}) -> {}", name, rc.id());
|
let msg = format!("fast-forward({}) -> {}", name, rc.id());
|
||||||
// println!("{}", msg);
|
|
||||||
lb.set_target(rc.id(), &msg)?;
|
lb.set_target(rc.id(), &msg)?;
|
||||||
repo.set_head(&name)?;
|
repo.set_head(&name)?;
|
||||||
repo.checkout_head(Some(build::CheckoutBuilder::default().force()))?;
|
repo.checkout_head(Some(build::CheckoutBuilder::default().force()))?;
|
||||||
|
|||||||
Reference in new issue
Block a user