This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / nunit20 / util / ProjectPath.cs
1 #region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
2 /************************************************************************************
3 '
4 ' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
5 ' Copyright  2000-2002 Philip A. Craig
6 '
7 ' This software is provided 'as-is', without any express or implied warranty. In no 
8 ' event will the authors be held liable for any damages arising from the use of this 
9 ' software.
10
11 ' Permission is granted to anyone to use this software for any purpose, including 
12 ' commercial applications, and to alter it and redistribute it freely, subject to the 
13 ' following restrictions:
14 '
15 ' 1. The origin of this software must not be misrepresented; you must not claim that 
16 ' you wrote the original software. If you use this software in a product, an 
17 ' acknowledgment (see the following) in the product documentation is required.
18 '
19 ' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
20 ' or Copyright  2000-2002 Philip A. Craig
21 '
22 ' 2. Altered source versions must be plainly marked as such, and must not be 
23 ' misrepresented as being the original software.
24 '
25 ' 3. This notice may not be removed or altered from any source distribution.
26 '
27 '***********************************************************************************/
28 #endregion
29
30 using System;
31 using System.IO;
32 using System.Text;
33 using System.Runtime.InteropServices;
34
35 namespace NUnit.Util
36 {
37         /// <summary>
38         /// Static methods for manipulating project paths, including both directories
39         /// and files. Some synonyms for System.Path methods are included as well.
40         /// </summary>
41         public class ProjectPath
42         {
43                 public const uint FILE_ATTRIBUTE_DIRECTORY  = 0x00000010;  
44                 public const uint FILE_ATTRIBUTE_NORMAL     = 0x00000080;  
45                 public const int MAX_PATH = 256;
46
47                 #region Public methods
48
49                 public static bool IsAssemblyFileType( string path )
50                 {
51                         string extension = Path.GetExtension( path );
52                         return extension == ".dll" || extension == ".exe";
53                 }
54
55                 /// <summary>
56                 /// Returns the relative path from a base directory to another
57                 /// directory or file.
58                 /// </summary>
59                 public static string RelativePath( string from, string to )
60                 {
61                         from = Canonicalize( from );
62                         to = Canonicalize( to );
63
64                         // Second argument to PathRelativeTo must be absolute
65                         if ( !Path.IsPathRooted( to ) )
66                                 return to;
67                         
68                         StringBuilder sb = new StringBuilder( MAX_PATH );
69
70                         // Return null if call fails
71                         if ( !PathRelativePathTo( sb, from, FILE_ATTRIBUTE_DIRECTORY, to, FILE_ATTRIBUTE_DIRECTORY ) )
72                                 return null;
73
74                         // Remove initial .\ from path if present
75                         if ( sb.Length >=2 && sb[0] == '.' && sb[1] == '\\' )
76                                 sb.Remove( 0, 2 );
77
78                         if ( sb.Length == 0 )
79                                 return null;
80
81                         return sb.ToString();
82                 }
83
84                 /// <summary>
85                 /// Return the canonical form of a path.
86                 public static string Canonicalize( string path )
87                 {
88                         StringBuilder sb = new StringBuilder( MAX_PATH );
89                         if ( !PathCanonicalize( sb, path ) )
90                                 throw new ArgumentException( string.Format( "Invalid path passed to PathCanonicalize: {0}", path ) );
91
92                         return sb.ToString();
93                 }
94
95                 /// <summary>
96                 /// True if the two paths are the same. However, two paths
97                 /// to the same file or directory using different network
98                 /// shares or drive letters are not treated as equal.
99                 /// </summary>
100                 public static bool SamePath( string path1, string path2 )
101                 {
102                         return Canonicalize(path1).ToLower() == Canonicalize(path2).ToLower();
103                 }
104
105                 /// <summary>
106                 /// True if the two paths are the same or if the second is
107                 /// directly or indirectly under the first. Note that paths 
108                 /// using different network shares or drive letters are 
109                 /// considered unrelated, even if they end up referencing
110                 /// the same subtrees in the file system.
111                 /// </summary>
112                 public static bool SamePathOrUnder( string path1, string path2 )
113                 {
114                         path1 = Canonicalize( path1 );
115                         path2 = Canonicalize( path2 );
116
117                         int length1 = path1.Length;
118                         int length2 = path2.Length;
119
120                         // if path1 is longer, then path2 can't be under it
121                         if ( length1 > length2 )
122                                 return false;
123
124                         // if lengths are the same, check for equality
125                         if ( length1 == length2 )
126                                 return path1.ToLower() == path2.ToLower();
127
128                         // path 2 is longer than path 1: see if initial parts match
129                         if ( path1.ToLower() != path2.Substring( 0, length1 ).ToLower() )
130                                 return false;
131                         
132                         // must match through or up to a directory separator boundary
133                         return  path2[length1-1] == Path.DirectorySeparatorChar ||
134                                         path2[length1] == Path.DirectorySeparatorChar;
135                 }
136
137                 #endregion
138
139                 #region Shlwapi functions used internally
140
141                 [DllImport("shlwapi.dll")]
142                 private static extern bool PathRelativePathTo(
143                         StringBuilder result,
144                         string from,
145                         uint attrFrom,
146                         string to,
147                         uint attrTo );
148
149                 [DllImport("shlwapi.dll")]
150                 private static extern bool PathCanonicalize(
151                         StringBuilder result,
152                         string path );
153
154                 [DllImport("shlwapi.dll")]
155                 private static extern int PathCommonPrefix(
156                         string file1,
157                         string file2,
158                         StringBuilder result );
159                         
160                 #endregion
161         }
162 }