aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart-vcs/tests/git_driver_test.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-08 19:52:18 +0900
committernsfisis <nsfisis@gmail.com>2026-05-08 19:52:18 +0900
commit5cb8fc4e306970764e84bb850da2c56f844c3b12 (patch)
tree0d66f3129a26138fcfee9402616b24929c40a017 /crates/mozart-vcs/tests/git_driver_test.rs
parentd83b9ef48775aeb31ba1909b29d5470e6d0ddaaa (diff)
downloadphp-mozart-5cb8fc4e306970764e84bb850da2c56f844c3b12.tar.gz
php-mozart-5cb8fc4e306970764e84bb850da2c56f844c3b12.tar.zst
php-mozart-5cb8fc4e306970764e84bb850da2c56f844c3b12.zip
fix(status): align with Composer's StatusCommand pipeline
Replace the dist-hash tree-diff implementation with Composer's VCS-level status flow: three buckets (errors / unpushed_changes / vcs_version_changes) populated via ChangeReportInterface / DvcsDownloaderInterface / VcsCapableDownloaderInterface, and a bitfield exit code (1|2|4) instead of always 1. Supporting work: - mozart-semver: add normalize_branch (VersionParser::normalizeBranch). - mozart-vcs: extend VcsDownloader trait with unpushed_changes / vcs_reference; port GitDownloader::getUnpushedChanges (HEAD-ref discovery + git diff --name-status remote...branch + two-pass fetch); fix git status invocation to use --untracked-files=no (Composer parity); add hasMetadataRepository preconditions to git/hg/svn local_changes; port VersionGuesser (git/hg/svn dispatch — Fossil omitted, feature branch detection runs sequentially instead of via async promises). - mozart-core: extend LocalPackage with pretty_version, package_type, installation_source, source, dist, extra; add InstallationSource and PackageReference. factory.rs reads them from installed.json. - mozart-registry: new download_manager mirroring DownloadManager::getDownloaderForPackage. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart-vcs/tests/git_driver_test.rs')
-rw-r--r--crates/mozart-vcs/tests/git_driver_test.rs72
1 files changed, 69 insertions, 3 deletions
diff --git a/crates/mozart-vcs/tests/git_driver_test.rs b/crates/mozart-vcs/tests/git_driver_test.rs
index 04b224b..2654665 100644
--- a/crates/mozart-vcs/tests/git_driver_test.rs
+++ b/crates/mozart-vcs/tests/git_driver_test.rs
@@ -168,11 +168,21 @@ fn test_git_downloader() {
let changes = downloader.local_changes(&target).unwrap();
assert!(changes.is_none(), "Expected no changes, got: {:?}", changes);
- // Make a local change and detect it
- std::fs::write(target.join("local_change.txt"), "change").unwrap();
+ // Untracked files alone must NOT count as local changes (matches
+ // Composer's `git status --porcelain --untracked-files=no`).
+ std::fs::write(target.join("untracked.txt"), "untracked").unwrap();
+ let changes = downloader.local_changes(&target).unwrap();
+ assert!(
+ changes.is_none(),
+ "Untracked files should be ignored, got: {:?}",
+ changes
+ );
+
+ // Modifying a tracked file is a local change.
+ std::fs::write(target.join("composer.json"), "{\"name\":\"changed\"}\n").unwrap();
let changes = downloader.local_changes(&target).unwrap();
assert!(changes.is_some());
- assert!(changes.unwrap().contains("local_change.txt"));
+ assert!(changes.unwrap().contains("composer.json"));
// Commit logs
let logs = downloader.commit_logs("v1.0.0", "v1.1.0", &target).unwrap();
@@ -184,6 +194,62 @@ fn test_git_downloader() {
}
#[test]
+fn test_git_downloader_unpushed_changes() {
+ if !has_git() {
+ eprintln!("Skipping test: git not available");
+ return;
+ }
+
+ let repo_dir = TempDir::new().unwrap();
+ let cache_dir = TempDir::new().unwrap();
+ let install_dir = TempDir::new().unwrap();
+ create_test_repo(repo_dir.path());
+
+ let process = ProcessExecutor::new();
+ let git_util = GitUtil::new(process, cache_dir.path().join("git"));
+ let downloader = GitDownloader::new(git_util);
+
+ let url = repo_dir.path().to_str().unwrap();
+ let target = install_dir.path().join("test-package");
+
+ downloader.download(url, "main", &target).unwrap();
+ downloader.install(url, "main", &target).unwrap();
+
+ // No commits added locally → no unpushed changes.
+ let unpushed = downloader.unpushed_changes(&target).unwrap();
+ assert!(
+ unpushed.is_none(),
+ "Expected no unpushed changes, got: {:?}",
+ unpushed
+ );
+
+ // Commit a local change without pushing.
+ let run = |args: &[&str]| {
+ let output = Command::new(args[0])
+ .args(&args[1..])
+ .current_dir(&target)
+ .env("GIT_AUTHOR_NAME", "Test")
+ .env("GIT_AUTHOR_EMAIL", "test@test.com")
+ .env("GIT_COMMITTER_NAME", "Test")
+ .env("GIT_COMMITTER_EMAIL", "test@test.com")
+ .output()
+ .unwrap();
+ assert!(output.status.success(), "Command failed: {:?}", args);
+ };
+ std::fs::write(target.join("local-only.txt"), "local-only").unwrap();
+ run(&["git", "add", "."]);
+ run(&["git", "commit", "-m", "Local-only commit"]);
+
+ let unpushed = downloader.unpushed_changes(&target).unwrap();
+ assert!(unpushed.is_some(), "Expected unpushed changes");
+ let body = unpushed.unwrap();
+ assert!(
+ body.contains("local-only.txt"),
+ "Expected diff body to mention local-only.txt, got: {body}"
+ );
+}
+
+#[test]
fn test_detect_driver() {
use mozart_vcs::driver::{DriverType, detect_driver};