Permalink
Browse files

[xbuild] Use files referenced by resx for dependency check.

For .resx resource files, check files referenced by the resx
file also, to determine whether to resgen it or not.

IsResgenRequired () has been taken from MonoDevelop
(main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1DotNetProjectHandler.cs)
  • Loading branch information...
1 parent 4abf81b commit ae1aee44394550966eb8acc1b935cd6ff5bb73e1 @radical radical committed Sep 15, 2010
View
89 mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/GenerateResource.cs
@@ -5,8 +5,11 @@
// Marek Sieradzki (marek.sieradzki@gmail.com)
// Paolo Molaro (lupus@ximian.com)
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
+// Lluis Sanchez Gual <lluis@novell.com>
+// Ankit Jain <jankit@novell.com>
//
// (C) 2005 Marek Sieradzki
+// Copyright 2010 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
@@ -36,6 +39,7 @@
using System.Collections.Generic;
using System.Resources;
using System.Reflection;
+using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Mono.XBuild.Tasks.GenerateResourceInternal;
@@ -73,7 +77,8 @@ public override bool Execute ()
string sourceFile = source.ItemSpec;
string outputFile = Path.ChangeExtension (sourceFile, "resources");
- result &= CompileResourceFile (sourceFile, outputFile);
+ if (IsResgenRequired (sourceFile, outputFile))
+ result &= CompileResourceFile (sourceFile, outputFile);
ITaskItem newItem = new TaskItem (source);
source.ItemSpec = outputFile;
@@ -93,7 +98,8 @@ public override bool Execute ()
continue;
}
- result &= CompileResourceFile (sources [i].ItemSpec, outputResources [i].ItemSpec);
+ if (IsResgenRequired (sources [i].ItemSpec, outputResources [i].ItemSpec))
+ result &= CompileResourceFile (sources [i].ItemSpec, outputResources [i].ItemSpec);
temporaryFilesWritten.Add (outputResources [i]);
}
}
@@ -103,6 +109,78 @@ public override bool Execute ()
return result;
}
+ // true if the resx file or any file referenced
+ // by the resx is newer than the .resources file
+ //
+ // Code taken from monodevelop
+ // main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MD1/MD1DotNetProjectHandler.cs
+ bool IsResgenRequired (string resx_filename, string resources_filename)
+ {
+ if (IsFileNewerThan (resx_filename, resources_filename)) {
+ Log.LogMessage (MessageImportance.Low,
+ "Resource file '{0}' is newer than the source file '{1}', skipping.",
+ resources_filename, resx_filename);
+ return true;
+ }
+
+ if (String.Compare (Path.GetExtension (resx_filename), ".resx", true) != 0)
+ return true;
+
+ // resx file, check for files referenced from there
+ XmlTextReader xr = null;
+ try {
+ // look for
+ // <data type="System.Resources.ResXFileRef, System.Windows.Forms" ..>
+ // <value>... filename;.. </value>
+ // </data>
+ xr = new XmlTextReader (resx_filename);
+ string basepath = Path.GetDirectoryName (resx_filename);
+ while (xr.Read ()) {
+ if (xr.NodeType != XmlNodeType.Element ||
+ String.Compare (xr.LocalName, "data") != 0)
+ continue;
+
+ string type = xr.GetAttribute ("type");
+ if (String.IsNullOrEmpty (type))
+ continue;
+
+ if (String.Compare (type, "System.Resources.ResXFileRef, System.Windows.Forms") != 0)
+ continue;
+
+ xr.ReadToDescendant ("value");
+ if (xr.NodeType != XmlNodeType.Element)
+ continue;
+
+ string value = xr.ReadElementContentAsString ();
+
+ string [] parts = value.Split (';');
+ if (parts.Length > 0) {
+ string referenced_filename = Utilities.FromMSBuildPath (
+ Path.Combine (basepath, parts [0]).Trim ());
+ if (File.Exists (referenced_filename) &&
+ IsFileNewerThan (referenced_filename, resources_filename))
+ return true;
+ }
+ }
+ } catch (XmlException) {
+ // Ignore xml errors, let resgen handle it
+ return true;
+ } finally {
+ if (xr != null)
+ xr.Close ();
+ }
+
+ return false;
+ }
+
+ // true if first is newer than second
+ static bool IsFileNewerThan (string first, string second)
+ {
+ FileInfo finfo_first = new FileInfo (first);
+ FileInfo finfo_second = new FileInfo (second);
+ return finfo_first.LastWriteTime > finfo_second.LastWriteTime;
+ }
+
#if false
private IResourceReader GetReader (Stream stream, string name)
{
@@ -154,13 +232,6 @@ private bool CompileResourceFile (string sname, string dname )
return false;
}
- if (File.GetLastWriteTime (sname) <= File.GetLastWriteTime (dname)) {
- Log.LogMessage (MessageImportance.Low,
- "Resource file '{0}' is newer than the source file '{1}', skipping.",
- dname, sname);
- return true;
- }
-
Resgen resgen = new Resgen ();
resgen.BuildEngine = this.BuildEngine;
resgen.UseSourcePath = true;
View
63 mcs/class/Microsoft.Build.Tasks/Microsoft.Build.Tasks/Utilities.cs
@@ -28,6 +28,7 @@
#if NET_2_0
using System;
+using System.IO;
namespace Microsoft.Build.Tasks {
internal static class Utilities {
@@ -42,6 +43,68 @@ internal static class Utilities {
}
}
+
+ 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);
+ }
+ }
+
}
}

0 comments on commit ae1aee4

Please sign in to comment.