@@ -12,11 +12,11 @@ use crate::{
1212} ;
1313use pixi_test_utils:: { MockRepoData , Package } ;
1414
15- fn write_basic_source_package_manifest ( path : & std:: path:: Path , version : & str , extra : & str ) {
15+ fn write_source_package_manifest ( path : & std:: path:: Path , name : & str , version : & str , extra : & str ) {
1616 let source_pixi_toml = format ! (
1717 r#"
1818[package]
19- name = "my-package "
19+ name = "{name} "
2020version = "{version}"
2121
2222[package.build]
@@ -27,12 +27,25 @@ backend = {{ name = "in-memory", version = "0.1.0" }}
2727 fs:: write ( path. join ( "pixi.toml" ) , source_pixi_toml) . unwrap ( ) ;
2828}
2929
30- fn write_basic_source_workspace_manifest ( path : & std:: path:: Path , channels : & [ & str ] ) {
30+ fn write_basic_source_package_manifest ( path : & std:: path:: Path , version : & str , extra : & str ) {
31+ write_source_package_manifest ( path, "my-package" , version, extra) ;
32+ }
33+
34+ fn write_source_workspace_manifest (
35+ path : & std:: path:: Path ,
36+ channels : & [ & str ] ,
37+ source_dependencies : & [ & str ] ,
38+ ) {
3139 let channels = channels
3240 . iter ( )
3341 . map ( |c| format ! ( r#""{c}""# ) )
3442 . collect :: < Vec < _ > > ( )
3543 . join ( ", " ) ;
44+ let source_dependencies = source_dependencies
45+ . iter ( )
46+ . map ( |name| format ! ( r#"{name} = {{ path = "./{name}" }}"# ) )
47+ . collect :: < Vec < _ > > ( )
48+ . join ( "\n " ) ;
3649 let manifest_content = format ! (
3750 r#"
3851[workspace]
@@ -41,13 +54,17 @@ platforms = ["{}"]
4154preview = ["pixi-build"]
4255
4356[dependencies]
44- my-package = {{ path = "./my-package" } }
57+ {source_dependencies }
4558"# ,
4659 Platform :: current( )
4760 ) ;
4861 fs:: write ( path, manifest_content) . unwrap ( ) ;
4962}
5063
64+ fn write_basic_source_workspace_manifest ( path : & std:: path:: Path , channels : & [ & str ] ) {
65+ write_source_workspace_manifest ( path, channels, & [ "my-package" ] ) ;
66+ }
67+
5168fn write_source_workspace_manifest_with_binary_dependencies (
5269 path : & std:: path:: Path ,
5370 channels : & [ & str ] ,
@@ -1515,3 +1532,67 @@ async fn test_source_timestamp_changes_for_explicit_update() {
15151532 "source timestamp should change when the package is explicitly updated"
15161533 ) ;
15171534}
1535+
1536+ #[ tokio:: test]
1537+ async fn test_source_timestamp_reuse_survives_sibling_metadata_change ( ) {
1538+ setup_tracing ( ) ;
1539+
1540+ let backend_override = BackendOverride :: from_memory ( PassthroughBackend :: instantiator ( ) ) ;
1541+ let pixi = PixiControl :: new ( )
1542+ . unwrap ( )
1543+ . with_backend_override ( backend_override) ;
1544+
1545+ let my_package_dir = pixi. workspace_path ( ) . join ( "my-package" ) ;
1546+ fs:: create_dir_all ( & my_package_dir) . unwrap ( ) ;
1547+ write_source_package_manifest ( & my_package_dir, "my-package" , "1.0.0" , "" ) ;
1548+
1549+ let other_package_dir = pixi. workspace_path ( ) . join ( "other-package" ) ;
1550+ fs:: create_dir_all ( & other_package_dir) . unwrap ( ) ;
1551+ write_source_package_manifest ( & other_package_dir, "other-package" , "1.0.0" , "" ) ;
1552+
1553+ write_source_workspace_manifest ( & pixi. manifest_path ( ) , & [ ] , & [ "my-package" , "other-package" ] ) ;
1554+
1555+ let initial_lock = pixi. update_lock_file ( ) . await . unwrap ( ) ;
1556+ let initial_my_timestamp = initial_lock
1557+ . get_conda_source_timestamp (
1558+ consts:: DEFAULT_ENVIRONMENT_NAME ,
1559+ Platform :: current ( ) ,
1560+ "my-package" ,
1561+ )
1562+ . expect ( "my-package should have a source timestamp" ) ;
1563+ let initial_other_timestamp = initial_lock
1564+ . get_conda_source_timestamp (
1565+ consts:: DEFAULT_ENVIRONMENT_NAME ,
1566+ Platform :: current ( ) ,
1567+ "other-package" ,
1568+ )
1569+ . expect ( "other-package should have a source timestamp" ) ;
1570+
1571+ std:: thread:: sleep ( Duration :: from_millis ( 25 ) ) ;
1572+ write_source_package_manifest ( & other_package_dir, "other-package" , "1.1.0" , "" ) ;
1573+
1574+ let relocked = pixi. update_lock_file ( ) . await . unwrap ( ) ;
1575+ let relocked_my_timestamp = relocked
1576+ . get_conda_source_timestamp (
1577+ consts:: DEFAULT_ENVIRONMENT_NAME ,
1578+ Platform :: current ( ) ,
1579+ "my-package" ,
1580+ )
1581+ . expect ( "my-package should still have a source timestamp" ) ;
1582+ let relocked_other_timestamp = relocked
1583+ . get_conda_source_timestamp (
1584+ consts:: DEFAULT_ENVIRONMENT_NAME ,
1585+ Platform :: current ( ) ,
1586+ "other-package" ,
1587+ )
1588+ . expect ( "other-package should still have a source timestamp" ) ;
1589+
1590+ assert_eq ! (
1591+ initial_my_timestamp, relocked_my_timestamp,
1592+ "unchanged source package should keep its timestamp even when a sibling source package changes"
1593+ ) ;
1594+ assert_ne ! (
1595+ initial_other_timestamp, relocked_other_timestamp,
1596+ "changed sibling source package should get a fresh timestamp"
1597+ ) ;
1598+ }
0 commit comments