// 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
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;
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;
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]);
}
}
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)
{
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;
#if NET_2_0
using System;
+using System.IO;
namespace Microsoft.Build.Tasks {
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);
+ }
+ }
+
}
}