@@ -9,9 +9,10 @@ use crate::core::manifest::target_defaults::{
99use crate :: core:: manifest:: {
1010 DependencyGitPathAmbiguous , DependencyGitRefWithoutGit , DependencyGitReferenceAmbiguous ,
1111 DependencyGitRegistryAmbiguous , DependencySourceMissing , DependencyWorkspaceNotFound ,
12- ManifestDependency , ManifestDependencyTable , ManifestDiagnosticAnchor , ManifestMetadata ,
13- ManifestSemanticError , PatchNotInWorkspaceRoot , PatchSourceConflict , PatchSourceInvalidUrl ,
14- ProfileCairoConflict , ProfileInheritanceInvalid , ProfileNameInvalid , Summary , Target ,
12+ LicensePathInvalid , ManifestDependency , ManifestDependencyTable , ManifestDiagnosticAnchor ,
13+ ManifestMetadata , ManifestSemanticError , PatchNotInWorkspaceRoot , PatchSourceConflict ,
14+ PatchSourceInvalidUrl , ProfileCairoConflict , ProfileInheritanceInvalid , ProfileNameInvalid ,
15+ ReadmePathInvalid , Summary , Target ,
1516} ;
1617use crate :: core:: package:: PackageId ;
1718use crate :: core:: registry:: { DEFAULT_REGISTRY_INDEX , DEFAULT_REGISTRY_INDEX_PATCH_SOURCE } ;
@@ -339,7 +340,12 @@ impl PackageInheritableFields {
339340 get_field ! ( edition, Edition ) ;
340341
341342 pub fn readme ( & self , workspace_root : & Utf8Path , package_root : & Utf8Path ) -> Result < PathOrBool > {
342- let Ok ( Some ( readme) ) = readme_for_package ( workspace_root, self . readme . as_ref ( ) ) else {
343+ let readme = readme_for_package (
344+ workspace_root,
345+ self . readme . as_ref ( ) ,
346+ Some ( ManifestDiagnosticAnchor :: workspace_package_field ( "readme" ) ) ,
347+ ) ?;
348+ let Some ( readme) = readme else {
343349 bail ! ( "`workspace.package.readme` was not defined" ) ;
344350 } ;
345351 diff_utf8_paths (
@@ -1275,13 +1281,25 @@ impl TomlManifest {
12751281 . clone ( )
12761282 . map ( |mw| match mw {
12771283 MaybeWorkspace :: Defined ( license_rel_path) => {
1278- abs_canonical_path ( "license" , manifest_path, & license_rel_path)
1284+ let anchor = ManifestDiagnosticAnchor :: package_field ( "license-file" ) ;
1285+ abs_canonical_path ( manifest_path, & license_rel_path, |path| {
1286+ ManifestSemanticError :: from ( LicensePathInvalid :: new ( path, Some ( anchor) ) )
1287+ . into ( )
1288+ } )
12791289 }
12801290 MaybeWorkspace :: Workspace ( _) => mw. resolve ( "license_file" , || {
1291+ let anchor =
1292+ ManifestDiagnosticAnchor :: workspace_package_field ( "license-file" ) ;
12811293 abs_canonical_path (
1282- "license" ,
12831294 workspace_manifest_path,
12841295 & inheritable_package. license_file ( ) ?,
1296+ |path| {
1297+ ManifestSemanticError :: from ( LicensePathInvalid :: new (
1298+ path,
1299+ Some ( anchor) ,
1300+ ) )
1301+ . into ( )
1302+ } ,
12851303 )
12861304 } ) ,
12871305 } )
@@ -1298,6 +1316,7 @@ impl TomlManifest {
12981316 } )
12991317 . transpose ( ) ?
13001318 . as_ref ( ) ,
1319+ Some ( ManifestDiagnosticAnchor :: package_field ( "readme" ) ) ,
13011320 ) ?,
13021321 repository : package
13031322 . repository
@@ -1884,6 +1903,7 @@ fn merge_profile(target: &TomlProfile, source: &TomlProfile) -> Result<TomlProfi
18841903pub fn readme_for_package (
18851904 package_root : & Utf8Path ,
18861905 readme : Option < & PathOrBool > ,
1906+ anchor : Option < ManifestDiagnosticAnchor > ,
18871907) -> Result < Option < Utf8PathBuf > > {
18881908 let file_name = match readme {
18891909 None => default_readme_from_package_root ( package_root. parent ( ) . unwrap ( ) ) ,
@@ -1896,16 +1916,27 @@ pub fn readme_for_package(
18961916 } ;
18971917
18981918 file_name
1899- . map ( |file_name| abs_canonical_path ( "readme" , package_root, file_name) )
1919+ . map ( |file_name| {
1920+ abs_canonical_path ( package_root, file_name, |path| match anchor. clone ( ) {
1921+ Some ( a) => {
1922+ ManifestSemanticError :: from ( ReadmePathInvalid :: new ( path, Some ( a) ) ) . into ( )
1923+ }
1924+ None => anyhow ! ( "failed to find readme at {path}" ) ,
1925+ } )
1926+ } )
19001927 . transpose ( )
19011928}
19021929
1903- /// Creates the absolute canonical path of the file and checks if it exists
1904- fn abs_canonical_path ( file_label : & str , prefix : & Utf8Path , path : & Utf8Path ) -> Result < Utf8PathBuf > {
1905- let path = prefix. parent ( ) . unwrap ( ) . join ( path) ;
1906- let path = fsx:: canonicalize_utf8 ( & path)
1907- . with_context ( || format ! ( "failed to find {file_label} at {path}" ) ) ?;
1908- Ok ( path)
1930+ /// Creates the absolute canonical path of the file and checks if it exists.
1931+ ///
1932+ /// `make_error` is called with the resolved (non-canonical) path when the file is not found.
1933+ fn abs_canonical_path (
1934+ prefix : & Utf8Path ,
1935+ path : & Utf8Path ,
1936+ make_error : impl FnOnce ( Utf8PathBuf ) -> anyhow:: Error ,
1937+ ) -> Result < Utf8PathBuf > {
1938+ let full_path = prefix. parent ( ) . unwrap ( ) . join ( path) ;
1939+ fsx:: canonicalize_utf8 ( & full_path) . map_err ( |_| make_error ( full_path) )
19091940}
19101941
19111942const DEFAULT_README_FILES : & [ & str ] = & [ "README.md" , "README.txt" , "README" ] ;
0 commit comments