Requires gmcs
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / Utilities.cs
index c92e14fb1cc488bbe4f3c335dbf80324fd32fd6c..579785db639fee097428f17babd5b7c9607352c5 100644 (file)
@@ -3,8 +3,10 @@
 //
 // Author:
 //   Marek Sieradzki (marek.sieradzki@gmail.com)
+//   Lluis Sanchez Gual <lluis@novell.com>
 //
 // (C) 2005 Marek Sieradzki
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -29,6 +31,7 @@
 
 using System;
 using System.Collections;
+using System.IO;
 using System.Text;
 
 namespace Microsoft.Build.BuildEngine {
@@ -56,15 +59,90 @@ namespace Microsoft.Build.BuildEngine {
                        StringBuilder sb = new StringBuilder ();
                        
                        foreach (char c in unescapedExpression) {
-                               if (charsToEscape.Contains (c)) {
+                               if (charsToEscape.Contains (c))
                                        sb.AppendFormat ("%{0:x2}", (int) c);
-                               else
+                               else
                                        sb.Append (c);
                        }
                        
                        return sb.ToString ();
                }
+               
+               // FIXME: add tests for this
+               internal static string Unescape (string escapedExpression)
+               {
+                       StringBuilder sb = new StringBuilder ();
+                       
+                       int i = 0;
+                       while (i < escapedExpression.Length) {
+                               sb.Append (Uri.HexUnescape (escapedExpression, ref i));
+                       }
+                       
+                       return sb.ToString ();
+               }
+
+               internal static string FromMSBuildPath (string relPath)
+               {
+                       if (relPath == null || relPath.Length == 0)
+                               return null;
+
+                       bool is_windows = Path.DirectorySeparatorChar == '\\';
+                       string path = relPath;
+                       if (!is_windows)
+                               path = path.Replace ("\\", "/");
+
+                       // a path with drive letter is invalid/unusable on non-windows
+                       if (!is_windows && char.IsLetter (path [0]) && path.Length > 1 && path[1] == ':')
+                               return null;
+
+                       if (System.IO.File.Exists (path)){
+                               return Path.GetFullPath (path);
+                       }
+
+                       if (Path.IsPathRooted (path)) {
+
+                               // Windows paths are case-insensitive. When mapping an absolute path
+                               // we can try to find the correct case for the path.
+
+                               string[] names = path.Substring (1).Split ('/');
+                               string part = "/";
+
+                               for (int n=0; n<names.Length; n++) {
+                                       string[] entries;
+
+                                       if (names [n] == ".."){
+                                               if (part == "/")
+                                                       return ""; // Can go further back. It's not an existing file
+                                               part = Path.GetFullPath (part + "/..");
+                                               continue;
+                                       }
+
+                                       entries = Directory.GetFileSystemEntries (part);
+
+                                       string fpath = null;
+                                       foreach (string e in entries) {
+                                               if (string.Compare (Path.GetFileName (e), names[n], true) == 0) {
+                                                       fpath = e;
+                                                       break;
+                                               }
+                                       }
+                                       if (fpath == null) {
+                                               // Part of the path does not exist. Can't do any more checking.
+                                               part = Path.GetFullPath (part);
+                                               for (; n < names.Length; n++)
+                                                       part += "/" + names[n];
+                                               return part;
+                                       }
+
+                                       part = fpath;
+                               }
+                               return Path.GetFullPath (part);
+                       } else {
+                               return Path.GetFullPath (path);
+                       }
+               }
        }
+
 }
 
 #endif