Fix all CreateInstance overloads for void
[mcs.git] / nunit24 / ClientUtilities / util / PathUtils.cs
blobb6e138301acddd3f401a7deda1e7989fe5ef2d5c
1 // ****************************************************************
2 // Copyright 2002-2003, Charlie Poole
3 // This is free software licensed under the NUnit license. You may
4 // obtain a copy of the license at http://nunit.org/?p=license&r=2.4
5 // ****************************************************************
7 using System;
8 using System.IO;
9 using System.Text;
10 using System.Reflection;
11 using System.Collections;
12 using System.Runtime.InteropServices;
14 namespace NUnit.Util
16 /// <summary>
17 /// Static methods for manipulating project paths, including both directories
18 /// and files. Some synonyms for System.Path methods are included as well.
19 /// </summary>
20 public class PathUtils
22 public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
23 public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
24 public const int MAX_PATH = 256;
26 protected static char DirectorySeparatorChar = Path.DirectorySeparatorChar;
27 protected static char AltDirectorySeparatorChar = Path.AltDirectorySeparatorChar;
29 #region Public methods
31 public static bool IsAssemblyFileType( string path )
33 string extension = Path.GetExtension( path ).ToLower();
34 return extension == ".dll" || extension == ".exe";
37 /// <summary>
38 /// Returns the relative path from a base directory to another
39 /// directory or file.
40 /// </summary>
41 public static string RelativePath( string from, string to )
43 if (from == null)
44 throw new ArgumentNullException (from);
45 if (to == null)
46 throw new ArgumentNullException (to);
47 if (!Path.IsPathRooted (to))
48 return to;
49 if (Path.GetPathRoot (from) != Path.GetPathRoot (to))
50 return null;
52 string[] _from = from.Split (PathUtils.DirectorySeparatorChar,
53 PathUtils.AltDirectorySeparatorChar);
54 string[] _to = to.Split (PathUtils.DirectorySeparatorChar,
55 PathUtils.AltDirectorySeparatorChar);
57 StringBuilder sb = new StringBuilder (Math.Max (from.Length, to.Length));
59 int last_common, min = Math.Min (_from.Length, _to.Length);
60 for (last_common = 0; last_common < min; ++last_common)
62 if (!_from [last_common].Equals (_to [last_common]))
63 break;
66 if (last_common < _from.Length)
67 sb.Append ("..");
68 for (int i = last_common + 1; i < _from.Length; ++i)
70 sb.Append (PathUtils.DirectorySeparatorChar).Append ("..");
73 if (sb.Length > 0)
74 sb.Append (PathUtils.DirectorySeparatorChar);
75 if (last_common < _to.Length)
76 sb.Append (_to [last_common]);
77 for (int i = last_common + 1; i < _to.Length; ++i)
79 sb.Append (PathUtils.DirectorySeparatorChar).Append (_to [i]);
82 return sb.ToString ();
85 /// <summary>
86 /// Return the canonical form of a path.
87 /// </summary>
88 public static string Canonicalize( string path )
90 ArrayList parts = new ArrayList(
91 path.Split( DirectorySeparatorChar, AltDirectorySeparatorChar ) );
93 for( int index = 0; index < parts.Count; )
95 string part = (string)parts[index];
97 switch( part )
99 case ".":
100 parts.RemoveAt( index );
101 break;
103 case "..":
104 parts.RemoveAt( index );
105 if ( index > 0 )
106 parts.RemoveAt( --index );
107 break;
108 default:
109 index++;
110 break;
114 return String.Join( DirectorySeparatorChar.ToString(), (string[])parts.ToArray( typeof( string ) ) );
117 /// <summary>
118 /// True if the two paths are the same. However, two paths
119 /// to the same file or directory using different network
120 /// shares or drive letters are not treated as equal.
121 /// </summary>
122 public static bool SamePath( string path1, string path2 )
124 return string.Compare( Canonicalize(path1), Canonicalize(path2), PathUtils.IsWindows() ) == 0;
127 /// <summary>
128 /// True if the two paths are the same or if the second is
129 /// directly or indirectly under the first. Note that paths
130 /// using different network shares or drive letters are
131 /// considered unrelated, even if they end up referencing
132 /// the same subtrees in the file system.
133 /// </summary>
134 public static bool SamePathOrUnder( string path1, string path2 )
136 path1 = Canonicalize( path1 );
137 path2 = Canonicalize( path2 );
139 int length1 = path1.Length;
140 int length2 = path2.Length;
142 // if path1 is longer, then path2 can't be under it
143 if ( length1 > length2 )
144 return false;
146 // if lengths are the same, check for equality
147 if ( length1 == length2 )
148 //return path1.ToLower() == path2.ToLower();
149 return string.Compare( path1, path2, IsWindows() ) == 0;
151 // path 2 is longer than path 1: see if initial parts match
152 //if ( path1.ToLower() != path2.Substring( 0, length1 ).ToLower() )
153 if ( string.Compare( path1, path2.Substring( 0, length1 ), IsWindows() ) != 0 )
154 return false;
156 // must match through or up to a directory separator boundary
157 return path2[length1-1] == DirectorySeparatorChar ||
158 path2[length1] == DirectorySeparatorChar;
161 public static string Combine( string path1, params string[] morePaths )
163 string result = path1;
164 foreach( string path in morePaths )
165 result = Path.Combine( result, path );
166 return result;
169 // TODO: This logic should be in shared source
170 public static string GetAssemblyPath( Assembly assembly )
172 string uri = assembly.CodeBase;
174 // If it wasn't loaded locally, use the Location
175 if ( !uri.StartsWith( Uri.UriSchemeFile ) )
176 return assembly.Location;
178 return GetAssemblyPathFromFileUri( uri );
181 // Separate method for testability
182 public static string GetAssemblyPathFromFileUri( string uri )
184 // Skip over the file://
185 int start = Uri.UriSchemeFile.Length + Uri.SchemeDelimiter.Length;
187 if ( PathUtils.DirectorySeparatorChar == '\\' )
189 if ( uri[start] == '/' && uri[start+2] == ':' )
190 ++start;
192 else
194 if ( uri[start] != '/' )
195 --start;
198 return uri.Substring( start );
200 #endregion
202 #region Helper Methods
203 private static bool IsWindows()
205 return PathUtils.DirectorySeparatorChar == '\\';
207 #endregion