#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
/************************************************************************************
'
' Copyright 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
' Copyright 2000-2002 Philip A. Craig
'
' This software is provided 'as-is', without any express or implied warranty. In no
' event will the authors be held liable for any damages arising from the use of this
' software.
'
' Permission is granted to anyone to use this software for any purpose, including
' commercial applications, and to alter it and redistribute it freely, subject to the
' following restrictions:
'
' 1. The origin of this software must not be misrepresented; you must not claim that
' you wrote the original software. If you use this software in a product, an
' acknowledgment (see the following) in the product documentation is required.
'
' Portions Copyright 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
' or Copyright 2000-2002 Philip A. Craig
'
' 2. Altered source versions must be plainly marked as such, and must not be
' misrepresented as being the original software.
'
' 3. This notice may not be removed or altered from any source distribution.
'
'***********************************************************************************/
#endregion
using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
namespace NUnit.Util
{
///
/// Static methods for manipulating project paths, including both directories
/// and files. Some synonyms for System.Path methods are included as well.
///
public class ProjectPath
{
public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
public const int MAX_PATH = 256;
#region Public methods
public static bool IsAssemblyFileType( string path )
{
string extension = Path.GetExtension( path );
return extension == ".dll" || extension == ".exe";
}
///
/// Returns the relative path from a base directory to another
/// directory or file.
///
public static string RelativePath( string from, string to )
{
from = Canonicalize( from );
to = Canonicalize( to );
// Second argument to PathRelativeTo must be absolute
if ( !Path.IsPathRooted( to ) )
return to;
StringBuilder sb = new StringBuilder( MAX_PATH );
// Return null if call fails
if ( !PathRelativePathTo( sb, from, FILE_ATTRIBUTE_DIRECTORY, to, FILE_ATTRIBUTE_DIRECTORY ) )
return null;
// Remove initial .\ from path if present
if ( sb.Length >=2 && sb[0] == '.' && sb[1] == '\\' )
sb.Remove( 0, 2 );
if ( sb.Length == 0 )
return null;
return sb.ToString();
}
///
/// Return the canonical form of a path.
public static string Canonicalize( string path )
{
StringBuilder sb = new StringBuilder( MAX_PATH );
if ( !PathCanonicalize( sb, path ) )
throw new ArgumentException( string.Format( "Invalid path passed to PathCanonicalize: {0}", path ) );
return sb.ToString();
}
///
/// True if the two paths are the same. However, two paths
/// to the same file or directory using different network
/// shares or drive letters are not treated as equal.
///
public static bool SamePath( string path1, string path2 )
{
return Canonicalize(path1).ToLower() == Canonicalize(path2).ToLower();
}
///
/// True if the two paths are the same or if the second is
/// directly or indirectly under the first. Note that paths
/// using different network shares or drive letters are
/// considered unrelated, even if they end up referencing
/// the same subtrees in the file system.
///
public static bool SamePathOrUnder( string path1, string path2 )
{
path1 = Canonicalize( path1 );
path2 = Canonicalize( path2 );
int length1 = path1.Length;
int length2 = path2.Length;
// if path1 is longer, then path2 can't be under it
if ( length1 > length2 )
return false;
// if lengths are the same, check for equality
if ( length1 == length2 )
return path1.ToLower() == path2.ToLower();
// path 2 is longer than path 1: see if initial parts match
if ( path1.ToLower() != path2.Substring( 0, length1 ).ToLower() )
return false;
// must match through or up to a directory separator boundary
return path2[length1-1] == Path.DirectorySeparatorChar ||
path2[length1] == Path.DirectorySeparatorChar;
}
#endregion
#region Shlwapi functions used internally
[DllImport("shlwapi.dll")]
private static extern bool PathRelativePathTo(
StringBuilder result,
string from,
uint attrFrom,
string to,
uint attrTo );
[DllImport("shlwapi.dll")]
private static extern bool PathCanonicalize(
StringBuilder result,
string path );
[DllImport("shlwapi.dll")]
private static extern int PathCommonPrefix(
string file1,
string file2,
StringBuilder result );
#endregion
}
}