@@ -206,13 +206,22 @@ protected override string GetCachedFileLocalPath(ILibraryInstallationState state
206206
207207 // For other filesystem libraries, the state.Name may be a either a file or folder
208208 // TODO: abstract file system
209- if ( File . Exists ( state . Name ) )
209+ ( bool isFile , string resolvedFilePath ) = LibraryNameIsFile ( state . Name ) ;
210+
211+ if ( isFile )
210212 {
211- return state . Name ;
213+ return resolvedFilePath ;
212214 }
213215
214216 // as a fallback, assume state.Name is a directory. If this path doesn't exist, it will
215217 // be handled elsewhere.
218+
219+ // root relative paths to the libman working directory
220+ if ( ! Path . IsPathRooted ( state . Name ) )
221+ {
222+ return Path . GetFullPath ( Path . Combine ( HostInteraction . WorkingDirectory , state . Name , sourceFile ) ) ;
223+ }
224+
216225 return Path . Combine ( state . Name , sourceFile ) ;
217226 }
218227
@@ -221,19 +230,41 @@ protected override Dictionary<string, string> GetFileMappings(ILibrary library,
221230 {
222231 Dictionary < string , string > fileMappings = new ( ) ;
223232 // Handle single-file edge cases for FileSystem
224- if ( library . Files . Count == 1
225- && fileFilters . Count == 1
226- && GetCachedFileLocalPath ( desiredState , library . Files . Keys . First ( ) ) == library . Name )
233+ ( bool librarySpecifiedIsFile , string resolvedFilePath ) = LibraryNameIsFile ( library . Name ) ;
234+ if ( librarySpecifiedIsFile && fileFilters . Count == 1 )
227235 {
228236 // direct 1:1 file mapping, allowing file rename
229237 string destinationFile = Path . Combine ( HostInteraction . WorkingDirectory , destination , fileFilters [ 0 ] ) ;
230238 destinationFile = FileHelpers . NormalizePath ( destinationFile ) ;
231239
232- fileMappings . Add ( destinationFile , library . Files . Keys . First ( ) ) ;
240+ // the library specified is a single file, so use that as the source directly
241+ fileMappings . Add ( destinationFile , resolvedFilePath ) ;
233242 return fileMappings ;
234243 }
235244
236245 return base . GetFileMappings ( library , fileFilters , mappingRoot , destination , desiredState , errors ) ;
237246 }
247+
248+ /// <summary>
249+ /// Checks if a specified library name corresponds to an existing file and returns the result along with the
250+ /// file path.
251+ /// </summary>
252+ /// <param name="libraryName">The name of the library being checked for existence as a file.</param>
253+ /// <returns>A tuple containing a boolean indicating if the file exists and the resolved file path.</returns>
254+ private ( bool , string ) LibraryNameIsFile ( string libraryName )
255+ {
256+ string filePath = libraryName ;
257+ if ( FileHelpers . IsHttpUri ( filePath ) )
258+ {
259+ return ( true , filePath ) ;
260+ }
261+
262+ if ( ! Path . IsPathRooted ( filePath ) )
263+ {
264+ filePath = Path . Combine ( HostInteraction . WorkingDirectory , filePath ) ;
265+ }
266+
267+ return ( File . Exists ( filePath ) , filePath ) ;
268+ }
238269 }
239270}
0 commit comments