Selaa lähdekoodia

fix: 将`last_modified_time`改为BFS & 修正未判断文件夹更新时间的bug (#84)

LoGin 5 kuukautta sitten
vanhempi
commit
f60cc4eb05

+ 66 - 40
dadk-user/src/executor/mod.rs

@@ -1,5 +1,5 @@
 use std::{
-    collections::BTreeMap,
+    collections::{BTreeMap, VecDeque},
     env::Vars,
     path::PathBuf,
     process::{Command, Stdio},
@@ -130,6 +130,7 @@ impl Executor {
                 } else {
                     task_log.set_install_status(InstallStatus::Failed);
                 }
+                task_log.set_install_time_now();
             }
 
             Action::Clean(_) => {
@@ -175,7 +176,12 @@ impl Executor {
     fn build(&mut self) -> Result<(), ExecutorError> {
         if let Some(status) = self.task_log().build_status() {
             if let Some(build_time) = self.task_log().build_time() {
-                let last_modified = last_modified_time(&self.entity.file_path(), build_time)?;
+                let mut last_modified = last_modified_time(&self.entity.file_path(), build_time)?; 
+                last_modified = core::cmp::max(
+                    last_modified,
+                    last_modified_time(&self.src_work_dir(), build_time)?,
+                );
+
                 if *status == BuildStatus::Success
                     && (self.entity.task().build_once || last_modified < *build_time)
                 {
@@ -212,21 +218,27 @@ impl Executor {
     }
 
     fn install(&self) -> Result<(), ExecutorError> {
+        log::trace!("dadk-user: install {}", self.entity.task().name_version());
         if let Some(status) = self.task_log().install_status() {
-            if let Some(build_time) = self.task_log().build_time() {
-                let last_modified = last_modified_time(&self.entity.file_path(), build_time)?;
+            if let Some(install_time) = self.task_log().install_time() {
+                let last_modified = last_modified_time(&self.build_dir.path, install_time)?;
+                let last_modified = core::cmp::max(
+                    last_modified,
+                    last_modified_time(&self.entity.file_path(), install_time)?,
+                );
+
                 if *status == InstallStatus::Success
-                    && (self.entity.task().install_once || last_modified < *build_time)
+                    && (self.entity.task().install_once || last_modified < *install_time)
                 {
                     info!(
-                        "Task {} has been installed successfully, skip install.",
+                        "install: Task {} not changed.",
                         self.entity.task().name_version()
                     );
                     return Ok(());
                 }
             }
         }
-
+        log::trace!("dadk-user: to do install {}", self.entity.task().name_version());
         return self.do_install();
     }
 
@@ -658,44 +670,58 @@ fn last_modified_time(
     path: &PathBuf,
     build_time: &DateTime<Utc>,
 ) -> Result<DateTime<Utc>, ExecutorError> {
-    let metadata = path
-        .metadata()
-        .map_err(|e| ExecutorError::InstallError(e.to_string()))?;
-
-    let last_modified = if metadata.is_dir() {
-        let mut last_modified = DateTime::<Utc>::from(SystemTime::UNIX_EPOCH);
-        for r in std::fs::read_dir(path).unwrap() {
-            if let Ok(entry) = r {
-                // 忽略编译产物目录
-                if entry.file_name() == "target" {
-                    continue;
-                }
+    let mut queue = VecDeque::new();
+    queue.push_back(path.clone());
+
+    let mut last_modified = DateTime::<Utc>::from(SystemTime::UNIX_EPOCH);
+
+    while let Some(current_path) = queue.pop_front() {
+        let metadata = current_path
+            .metadata()
+            .map_err(|e| ExecutorError::InstallError(e.to_string()))?;
+
+        if metadata.is_dir() {
+            for r in std::fs::read_dir(&current_path).unwrap() {
+                if let Ok(entry) = r {
+                    // 忽略编译产物目录
+                    if entry.file_name() == "target" {
+                        continue;
+                    }
 
-                let metadata = entry.metadata().unwrap();
-                if metadata.is_dir() {
-                    // 如果是子目录,则递归找改子目录下的文件最后的更新时间
-                    last_modified = std::cmp::max(
-                        last_modified,
-                        last_modified_time(&entry.path(), build_time)?,
-                    );
-                } else {
+                    let entry_path = entry.path();
+                    let entry_metadata = entry.metadata().unwrap();
                     // 比较文件的修改时间和last_modified,取最大值
-                    last_modified = std::cmp::max(
-                        last_modified,
-                        DateTime::<Utc>::from(metadata.modified().unwrap()),
-                    );
-                }
+                    let file_modified = DateTime::<Utc>::from(entry_metadata.modified().unwrap());
+                    last_modified = std::cmp::max(last_modified, file_modified);
 
-                // 如果其中某一个文件的修改时间在build_time之后,则直接返回,不用继续递归
-                if last_modified > *build_time {
-                    return Ok(last_modified);
+                    // 如果其中某一个文件的修改时间在build_time之后,则直接返回,不用继续搜索
+                    if last_modified > *build_time {
+                        return Ok(last_modified);
+                    }
+
+                    if entry_metadata.is_dir() {
+                        // 如果是子目录,则将其加入队列
+                        queue.push_back(entry_path);
+                    }
                 }
             }
+        } else {
+            // 如果是文件,直接比较修改时间
+            let file_modified = DateTime::<Utc>::from(metadata.modified().unwrap());
+            last_modified = std::cmp::max(last_modified, file_modified);
+
+            // 如果其中某一个文件的修改时间在build_time之后,则直接返回,不用继续递归
+            if last_modified > *build_time {
+                return Ok(last_modified);
+            }
         }
-        last_modified
-    } else {
-        DateTime::<Utc>::from(metadata.modified().unwrap())
-    };
+    }
 
-    return Ok(last_modified);
+    if last_modified == DateTime::<Utc>::from(SystemTime::UNIX_EPOCH) {
+        return Err(ExecutorError::InstallError(format!(
+            "Failed to get last modified time for path: {}",
+            path.display()
+        )));
+    }
+    Ok(last_modified)
 }

+ 2 - 2
dadk-user/src/parser/mod.rs

@@ -175,7 +175,7 @@ impl Parser {
                         continue;
                     }
                     let extension: &std::ffi::OsStr = extension.unwrap();
-                    if extension.to_ascii_lowercase() != "dadk" {
+                    if extension.to_ascii_lowercase() != "toml" {
                         continue;
                     }
                     // 找到一个配置文件, 加入列表
@@ -217,10 +217,10 @@ impl Parser {
     /// * `Ok(DADKTask)` - 生成好的任务
     /// * `Err(ParserError)` - 解析错误
     pub(super) fn parse_config_file(&self, config_file: &PathBuf) -> Result<DADKTask> {
+        log::trace!("Parsing config file {}", config_file.display());
         // 从toml文件中解析出DADKTask
         let mut task: DADKTask = Self::parse_toml_file(config_file)?;
 
-        debug!("Parsed config file {}: {:?}", config_file.display(), task);
 
         // 去除字符串中的空白字符
         task.trim();

+ 10 - 2
dadk-user/src/parser/task_log.rs

@@ -15,6 +15,7 @@ pub struct TaskLog {
         skip_serializing_if = "Option::is_none"
     )]
     build_timestamp: Option<DateTime<Utc>>,
+    install_timestamp: Option<DateTime<Utc>>,
     /// 任务构建状态
     build_status: Option<BuildStatus>,
     /// 任务安装状态
@@ -36,6 +37,7 @@ impl TaskLog {
         Self {
             build_timestamp: None,
             build_status: None,
+            install_timestamp: None,
             install_status: None,
         }
     }
@@ -45,16 +47,22 @@ impl TaskLog {
         self.build_timestamp = Some(time);
     }
 
-    #[allow(dead_code)]
     pub fn build_time(&self) -> Option<&DateTime<Utc>> {
         self.build_timestamp.as_ref()
     }
 
-    #[allow(dead_code)]
     pub fn set_build_time_now(&mut self) {
         self.build_timestamp = Some(Utc::now());
     }
 
+    pub fn install_time(&self) -> Option<&DateTime<Utc>> {
+        self.install_timestamp.as_ref()
+    }
+
+    pub fn set_install_time_now(&mut self) {
+        self.install_timestamp = Some(Utc::now());
+    }
+
     pub fn set_build_status(&mut self, status: BuildStatus) {
         self.build_status = Some(status);
     }

+ 1 - 0
dadk-user/src/utils/file.rs

@@ -46,6 +46,7 @@ impl FileUtils {
 
     /// 递归地复制给定目录下所有文件到另一个文件夹中
     pub fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), String> {
+        log::trace!("FileUtils::copy_dir_all: src: {:?}, dst: {:?}", src, dst);
         let mut cmd = Command::new("cp");
         cmd.arg("-r").arg("-f").arg("./").arg(dst);