diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05a2129..b31c7cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,6 +102,24 @@ jobs: throw 'error on rg.exe' } + - if: matrix.os == 'windows-latest' + name: "Integration test: [windows] [sync-self]" + env: + SYNC_DIR: "sync-self" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mkdir sync-self + + copy "target\debug\tool.exe" "sync-self\tool.exe" + + sync-self\tool.exe --config="tests\sync-self-downgrade.toml" sync + + $old_version = sync-self\tool.exe --version + + if ($old_version -notmatch 'tool-sync 0.2.0') { + throw 'self-update is not the same' + } + - if: matrix.os != 'windows-latest' name: "Integration test: [unix] [sync-full]" env: diff --git a/src/sync/install.rs b/src/sync/install.rs index d0ad5e0..95b3f86 100644 --- a/src/sync/install.rs +++ b/src/sync/install.rs @@ -1,7 +1,7 @@ use indicatif::ProgressBar; use self_replace; -use std::env; use std::error::Error; +use std::env; use std::fs; use std::path::{Path, PathBuf}; use tempdir::TempDir; @@ -19,6 +19,7 @@ use super::progress::SyncProgress; pub struct Installer<'a> { store_directory: &'a Path, + self_exe: PathBuf, tmp_dir: TempDir, sync_progress: SyncProgress, } @@ -34,6 +35,7 @@ impl<'a> Installer<'a> { } Ok(tmp_dir) => Installer { store_directory, + self_exe: env::current_exe().unwrap(), tmp_dir, sync_progress, }, @@ -89,7 +91,12 @@ impl<'a> Installer<'a> { Err(unpack_err.to_string().into()) } Ok(tool_path) => { - copy_file(tool_path, self.store_directory, &tool_asset.exe_name)?; + copy_file( + tool_path, + self.store_directory, + &tool_asset.exe_name, + &self.self_exe, + )?; Ok(()) } @@ -98,14 +105,24 @@ impl<'a> Installer<'a> { } } -fn copy_file(tool_path: PathBuf, store_directory: &Path, exe_name: &str) -> std::io::Result<()> { +fn copy_file( + tool_path: PathBuf, + store_directory: &Path, + exe_name: &str, + self_path: &Path, +) -> std::io::Result<()> { let exe_name = mk_exe_name(exe_name); let mut install_path = PathBuf::new(); install_path.push(store_directory); install_path.push(exe_name); - if &install_path == &env::current_exe()? { + // DANGER: This check does not really mean two paths resolve to the + // same file. For example, the exe path /a/b/c.exe is not the same + // as install path b/c.exe if the current working directory is in /d + // instead of /a. Perhaps expand store directory to absolute or use + // `BurntSushi/same-file`? + if self_path.ends_with(&install_path) { // May have issues with a symbolic links. The assumption is that // the store directory is in the PATH and the executable itself // where this issue should not apply but may be an edge case. diff --git a/tests/sync-self-downgrade.toml b/tests/sync-self-downgrade.toml new file mode 100644 index 0000000..edea670 --- /dev/null +++ b/tests/sync-self-downgrade.toml @@ -0,0 +1,4 @@ +store_directory = "sync-self" + +[tool-sync] +tag = "v0.2.0"