Add retrying of failed tests by default to reduce flaky tests (#5461)
[mono.git] / mcs / tools / gacutil / driver.cs
index e24d7c0b2927fb4e8501801ed0757e18d2a51676..47c4ac8df96bd44da12af6c98d5309da235cbc89 100644 (file)
@@ -14,7 +14,6 @@ using System;
 using System.IO;
 using System.Diagnostics;
 using System.Text;
-using System.Reflection;
 using System.Collections;
 using System.Globalization;
 using System.Runtime.InteropServices;
@@ -23,6 +22,8 @@ using System.Security.Cryptography;
 using Mono.Security;
 using Mono.Security.Cryptography;
 
+using IKVM.Reflection;
+
 namespace Mono.Tools {
 
        public class Driver {
@@ -48,6 +49,7 @@ namespace Mono.Tools {
 
                private static bool silent;
                static bool in_bootstrap;
+               private static Universe _universe;
 
                public static int Main (string [] args)
                {
@@ -244,7 +246,7 @@ namespace Mono.Tools {
                        AssemblyName an = null;
 
                        try {
-                               assembly = Assembly.LoadFrom (name);
+                               assembly = ReflectionOnlyLoadFrom (name);
                        } catch {
                                WriteLine (string.Format (failure_msg, name) + "The file specified is not a valid assembly.");
                                return false;
@@ -324,6 +326,11 @@ namespace Mono.Tools {
 
                        Copy (name, asmb_path, true);
 
+                       var name_pdb = Path.ChangeExtension (name, ".pdb");
+                       if (File.Exists (name_pdb)) {
+                               Copy (name_pdb, Path.ChangeExtension (asmb_path, ".pdb"), true);
+                       }
+
                        foreach (string ext in siblings) {
                                string sibling = String.Concat (name, ext);
                                if (File.Exists (sibling))
@@ -352,12 +359,27 @@ namespace Mono.Tools {
                                        Environment.Exit (1);
                                }
                                if (Path.DirectorySeparatorChar == '/') {
-                                       string pkg_path = "../gac/" + an.Name + "/" + version_token + "/" + asmb_file;
+                                       string pkg_path_abs = Path.Combine (gacdir, Path.Combine (an.Name, Path.Combine (version_token, asmb_file)));
+                                       string pkg_path = AbsoluteToRelativePath (ref_dir, pkg_path_abs);
                                        symlink (pkg_path, ref_path);
 
+                                       var pdb_pkg_path = Path.ChangeExtension (pkg_path, ".pdb");
+                                       var pdb_ref_path = Path.ChangeExtension (ref_path, ".pdb");
+
+                                       if (File.Exists (pdb_pkg_path)) {
+                                               symlink (pdb_pkg_path, pdb_ref_path);
+                                       } else {
+                                               try {
+                                                       File.Delete (pdb_ref_path);
+                                               } catch {
+                                                       // Ignore error, just delete files that should not be there.
+                                               }
+                                       }
+
                                        foreach (string ext in siblings) {
                                                string sibling = String.Concat (pkg_path, ext);
                                                string sref = String.Concat (ref_path, ext);
+
                                                if (File.Exists (sibling))
                                                        symlink (sibling, sref);
                                                else {
@@ -385,6 +407,88 @@ namespace Mono.Tools {
                        return true;
                }
 
+               //from MonoDevelop.Core.FileService
+               unsafe static string AbsoluteToRelativePath (string baseDirectoryPath, string absPath)
+               {
+                       if (!Path.IsPathRooted (absPath) || string.IsNullOrEmpty (baseDirectoryPath))
+                               return absPath;
+
+                       absPath = Path.GetFullPath (absPath);
+                       baseDirectoryPath = Path.GetFullPath (baseDirectoryPath).TrimEnd (Path.DirectorySeparatorChar);
+
+                       fixed (char* bPtr = baseDirectoryPath, aPtr = absPath) {
+                               var bEnd = bPtr + baseDirectoryPath.Length;
+                               var aEnd = aPtr + absPath.Length;
+                               char* lastStartA = aEnd;
+                               char* lastStartB = bEnd;
+
+                               int indx = 0;
+                               // search common base path
+                               var a = aPtr;
+                               var b = bPtr;
+                               while (a < aEnd) {
+                                       if (*a != *b)
+                                               break;
+                                       if (IsSeparator (*a)) {
+                                               indx++;
+                                               lastStartA = a + 1;
+                                               lastStartB = b;
+                                       }
+                                       a++;
+                                       b++;
+                                       if (b >= bEnd) {
+                                               if (a >= aEnd || IsSeparator (*a)) {
+                                                       indx++;
+                                                       lastStartA = a + 1;
+                                                       lastStartB = b;
+                                               }
+                                               break;
+                                       }
+                               }
+                               if (indx == 0)
+                                       return absPath;
+
+                               if (lastStartA >= aEnd)
+                                       return ".";
+
+                               // handle case a: some/path b: some/path/deeper...
+                               if (a >= aEnd) {
+                                       if (IsSeparator (*b)) {
+                                               lastStartA = a + 1;
+                                               lastStartB = b;
+                                       }
+                               }
+
+                               // look how many levels to go up into the base path
+                               int goUpCount = 0;
+                               while (lastStartB < bEnd) {
+                                       if (IsSeparator (*lastStartB))
+                                               goUpCount++;
+                                       lastStartB++;
+                               }
+                               var size = goUpCount * 2 + goUpCount + aEnd - lastStartA;
+                               var result = new char [size];
+                               fixed (char* rPtr = result) {
+                                       // go paths up
+                                       var r = rPtr;
+                                       for (int i = 0; i < goUpCount; i++) {
+                                               *(r++) = '.';
+                                               *(r++) = '.';
+                                               *(r++) = Path.DirectorySeparatorChar;
+                                       }
+                                       // copy the remaining absulute path
+                                       while (lastStartA < aEnd)
+                                               *(r++) = *(lastStartA++);
+                               }
+                               return new string (result);
+                       }
+               }
+
+               static bool IsSeparator (char ch)
+               {
+                       return ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar || ch == Path.VolumeSeparatorChar;
+               }
+
                private static void Uninstall (string name, string package, string gacdir, string libdir, bool listMode, ref int uninstalled, ref int failures)
                {
                        string [] assembly_pieces = name.Split (new char[] { ',' });
@@ -431,12 +535,8 @@ namespace Mono.Tools {
 
                                if (File.Exists (Path.Combine (dir, assembly_name + ".dll"))) {
                                        extension = ".dll";
-                               } else if (File.Exists (Path.Combine (dir, assembly_name + ".DLL"))) {
-                                       extension = ".DLL";
                                } else if (File.Exists (Path.Combine (dir, assembly_name + ".exe"))) {
                                        extension = ".exe";
-                               } else if (File.Exists (Path.Combine (dir, assembly_name + ".EXE"))) {
-                                       extension = ".EXE";
                                } else {
                                        failures++;
                                        WriteLine("Cannot find the assembly: " + assembly_name);
@@ -646,12 +746,27 @@ namespace Mono.Tools {
                        }
                }
 
+               private static Universe GetUniverse () {
+                       if (_universe == null) {
+                               _universe = new Universe (UniverseOptions.MetadataOnly);
+                       }
+                       return _universe;
+               }
+
+               private static Assembly ReflectionOnlyLoadFrom (string fileName)
+               {
+                       return GetUniverse ().LoadFile (fileName);
+               }
+               private static AssemblyName GetCorlibName ()
+               {
+                       return GetUniverse ().Mscorlib.GetName ();
+               }
+
                private static bool CheckReferencedAssemblies (AssemblyName an)
                {
-                       AppDomain d = null;
                        try {
-                               Assembly a = Assembly.LoadFrom (an.CodeBase);
-                               AssemblyName corlib = typeof (object).Assembly.GetName ();
+                               Assembly a = ReflectionOnlyLoadFrom (an.CodeBase);
+                               AssemblyName corlib = GetCorlibName ();
 
                                foreach (AssemblyName ref_an in a.GetReferencedAssemblies ()) {
                                        if (ref_an.Name == corlib.Name) // Just do a string compare so we can install on diff versions
@@ -665,12 +780,6 @@ namespace Mono.Tools {
                        } catch (Exception e) {
                                WriteLine (e.ToString ()); // This should be removed pre beta3
                                return false;
-                       } finally {
-                               if (d != null) {
-                                       try {
-                                               AppDomain.Unload (d);
-                                       } catch { }
-                               }
                        }
 
                        return true;
@@ -702,8 +811,8 @@ namespace Mono.Tools {
 
                static bool LoadConfig (bool quiet)
                {
-                       MethodInfo config = typeof (System.Environment).GetMethod ("GetMachineConfigPath",
-                               BindingFlags.Static | BindingFlags.NonPublic);
+                       System.Reflection.MethodInfo config = typeof (System.Environment).GetMethod ("GetMachineConfigPath",
+                               System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
 
                        if (config != null) {
                                string path = (string) config.Invoke (null, null);
@@ -734,7 +843,7 @@ namespace Mono.Tools {
 
                        // Note: MustVerify is based on the original token (by design). Public key
                        // remapping won't affect if the assembly is verified or not.
-                       if (StrongNameManager.MustVerify (an)) {
+                       if (StrongNameManager.MustVerify (new System.Reflection.AssemblyName (an.FullName))) {
                                RSA rsa = CryptoConvert.FromCapiPublicKeyBlob (publicKey, 12);
                                StrongName sn = new StrongName (rsa);
                                if (sn.Verify (assemblyFile)) {
@@ -749,7 +858,7 @@ namespace Mono.Tools {
 
                private static bool IsSwitch (string arg)
                {
-                       return (arg [0] == '-' || (arg [0] == '/' && !arg.EndsWith (".dll") && arg.IndexOf ('/', 1) < 0 ) );
+                       return (arg [0] == '-' || (arg [0] == '/' && !arg.EndsWith (".dll") && !arg.EndsWith (".exe") && arg.IndexOf ('/', 1) < 0 ) );
                }
 
                private static Command GetCommand (string arg)
@@ -801,20 +910,20 @@ namespace Mono.Tools {
                public static extern int symlink (string oldpath, string newpath);
 
                private static string GetGacDir () {
-                       PropertyInfo gac = typeof (System.Environment).GetProperty ("GacPath",
-                                       BindingFlags.Static|BindingFlags.NonPublic);
+                       System.Reflection.PropertyInfo gac = typeof (System.Environment).GetProperty ("GacPath",
+                                       System.Reflection.BindingFlags.Static|System.Reflection.BindingFlags.NonPublic);
                        if (gac == null) {
                                WriteLine ("ERROR: Mono runtime not detected, please use " +
                                                "the mono runtime for gacutil.exe");
                                Environment.Exit (1);
                        }
-                       MethodInfo get_gac = gac.GetGetMethod (true);
+                       System.Reflection.MethodInfo get_gac = gac.GetGetMethod (true);
                        return (string) get_gac.Invoke (null, null);
                }
 
                private static string GetLibDir () {
-                       MethodInfo libdir = typeof (System.Environment).GetMethod ("internalGetGacPath",
-                                       BindingFlags.Static|BindingFlags.NonPublic);
+                       System.Reflection.MethodInfo libdir = typeof (System.Environment).GetMethod ("internalGetGacPath",
+                                       System.Reflection.BindingFlags.Static|System.Reflection.BindingFlags.NonPublic);
                        if (libdir == null) {
                                WriteLine ("ERROR: Mono runtime not detected, please use " +
                                                "the mono runtime for gacutil.exe");