use anyhow::Result;
use crate::common::{ManifestBuilder, TestProject};
#[tokio::test]
async fn test_incremental_resolves_only_specified_deps() -> Result<()> {
agpm_cli::test_utils::init_test_logging(None);
let project = TestProject::new().await?;
let remote = project.create_source_repo("remote").await?;
remote.add_resource("agents", "agent1", "---\nname: agent1\n---\nOriginal agent1").await?;
remote.commit_all("Initial agent1")?;
remote.tag_version("v1.0.0")?;
remote.add_resource("agents", "agent2", "---\nname: agent2\n---\nOriginal agent2").await?;
remote.commit_all("Add agent2")?;
remote.tag_version("v1.1.0")?;
let remote_url = remote.bare_file_url(project.sources_path()).await?;
let manifest = ManifestBuilder::new()
.add_source("remote", &remote_url)
.add_agent("agent1", |d| d.source("remote").path("agents/agent1.md").version("v1.0.0"))
.add_agent("agent2", |d| d.source("remote").path("agents/agent2.md").version("v1.1.0"))
.build();
project.write_manifest(&manifest).await?;
let output = project.run_agpm(&["install"])?;
assert!(output.success, "Install should succeed. Stderr: {}", output.stderr);
let agent1_path = project.project_path().join(".claude/agents/agpm/agent1.md");
let agent2_path = project.project_path().join(".claude/agents/agpm/agent2.md");
assert!(tokio::fs::metadata(&agent1_path).await.is_ok(), "Agent1 should exist");
assert!(tokio::fs::metadata(&agent2_path).await.is_ok(), "Agent2 should exist");
remote.add_resource("agents", "agent1", "---\nname: agent1\n---\nUpdated agent1").await?;
remote.commit_all("Update agent1")?;
remote.tag_version("v1.0.1")?;
remote.add_resource("agents", "agent2", "---\nname: agent2\n---\nUpdated agent2").await?;
remote.commit_all("Update agent2")?;
remote.tag_version("v1.1.1")?;
let bare_path = project.sources_path().join("remote.git");
std::fs::remove_dir_all(&bare_path)?;
remote.to_bare_repo(&bare_path).await?;
let manifest = ManifestBuilder::new()
.add_source("remote", &remote_url)
.add_agent("agent1", |d| d.source("remote").path("agents/agent1.md").version("~v1.0.0"))
.add_agent("agent2", |d| d.source("remote").path("agents/agent2.md").version("~v1.1.0"))
.build();
project.write_manifest(&manifest).await?;
let output = project.run_agpm(&["update", "agent1"])?;
assert!(output.success, "Update should succeed. Stderr: {}", output.stderr);
let lockfile = project.load_lockfile()?;
let agent1 =
lockfile.agents.iter().find(|a| a.name == "agents/agent1").expect("agent1 not found");
assert_eq!(agent1.version, Some("v1.0.1".to_string()));
let agent2 =
lockfile.agents.iter().find(|a| a.name == "agents/agent2").expect("agent2 not found");
assert_eq!(agent2.version, Some("v1.1.0".to_string()));
Ok(())
}
#[tokio::test]
async fn test_incremental_multiple_dependencies() -> Result<()> {
agpm_cli::test_utils::init_test_logging(None);
let project = TestProject::new().await?;
let remote = project.create_source_repo("remote").await?;
remote.add_resource("agents", "agent1", "---\nname: agent1\n---\nOriginal agent1").await?;
remote.add_resource("agents", "agent2", "---\nname: agent2\n---\nOriginal agent2").await?;
remote.add_resource("snippets", "snippet1", "# Snippet 1\nOriginal snippet1").await?;
remote.commit_all("Initial resources")?;
remote.tag_version("v1.0.0")?;
let remote_url = remote.bare_file_url(project.sources_path()).await?;
let manifest = ManifestBuilder::new()
.add_source("remote", &remote_url)
.add_standard_agent("agent1", "remote", "agents/agent1.md")
.add_standard_agent("agent2", "remote", "agents/agent2.md")
.add_standard_snippet("snippet1", "remote", "snippets/snippet1.md")
.build();
project.write_manifest(&manifest).await?;
let output = project.run_agpm(&["install"])?;
assert!(output.success, "Install should succeed. Stderr: {}", output.stderr);
remote.add_resource("agents", "agent1", "---\nname: agent1\n---\nUpdated agent1").await?;
remote.add_resource("agents", "agent2", "---\nname: agent2\n---\nUpdated agent2").await?;
remote.add_resource("snippets", "snippet1", "# Snippet 1\nUpdated snippet1").await?;
remote.commit_all("Update all")?;
remote.tag_version("v1.1.0")?;
let bare_path = project.sources_path().join("remote.git");
std::fs::remove_dir_all(&bare_path)?;
remote.to_bare_repo(&bare_path).await?;
let manifest = ManifestBuilder::new()
.add_source("remote", &remote_url)
.add_agent("agent1", |d| d.source("remote").path("agents/agent1.md").version("^v1.0.0"))
.add_agent("agent2", |d| d.source("remote").path("agents/agent2.md").version("^v1.0.0"))
.add_snippet("snippet1", |d| {
d.source("remote").path("snippets/snippet1.md").version("^v1.0.0")
})
.build();
project.write_manifest(&manifest).await?;
let output = project.run_agpm(&["update", "agent1", "snippet1"])?;
assert!(
output.success,
"Update should succeed. Stderr: {}\nStdout: {}",
output.stderr, output.stdout
);
let lockfile_content = project.read_lockfile().await?;
let lockfile = project.load_lockfile()?;
let agent1 =
lockfile.agents.iter().find(|a| a.name == "agents/agent1").expect("agent1 not found");
assert_eq!(
agent1.version,
Some("v1.1.0".to_string()),
"agent1 should be v1.1.0, got {:?}. Lockfile:\n{}",
agent1.version,
lockfile_content
);
let agent2 =
lockfile.agents.iter().find(|a| a.name == "agents/agent2").expect("agent2 not found");
assert_eq!(agent2.version, Some("v1.0.0".to_string()));
let snippet1 = lockfile
.snippets
.iter()
.find(|s| s.name == "snippets/snippet1")
.expect("snippet1 not found");
assert_eq!(snippet1.version, Some("v1.1.0".to_string()));
Ok(())
}
#[tokio::test]
async fn test_incremental_nonexistent_dependency() -> Result<()> {
agpm_cli::test_utils::init_test_logging(None);
let project = TestProject::new().await?;
let remote = project.create_source_repo("remote").await?;
remote.add_resource("agents", "agent1", "---\nname: agent1\n---\nAgent content").await?;
remote.commit_all("Initial commit")?;
remote.tag_version("v1.0.0")?;
let remote_url = remote.bare_file_url(project.sources_path()).await?;
let manifest = ManifestBuilder::new()
.add_source("remote", &remote_url)
.add_standard_agent("agent1", "remote", "agents/agent1.md")
.build();
project.write_manifest(&manifest).await?;
let output = project.run_agpm(&["install"])?;
assert!(output.success, "Install should succeed. Stderr: {}", output.stderr);
let initial_lockfile = project.read_lockfile().await?;
let output = project.run_agpm(&["update", "nonexistent"])?;
assert!(output.success, "Update should succeed. Stderr: {}", output.stderr);
let final_lockfile = project.read_lockfile().await?;
assert_eq!(
initial_lockfile, final_lockfile,
"Lockfile should be unchanged when updating non-existent dependency"
);
Ok(())
}