From b3e7ae084ce5e40c3083716b81af322f7806d1d2 Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Thu, 15 Dec 2016 11:31:16 -0500 Subject: [PATCH 1/2] [msbuild] Don't rewrite embedded.mobileprovision or archived-expanded-entitlements.xcent This patch prevents those 2 files from being rewritten in cases where the contents would not change from what was already there previously. This is a partial fix for https://bugzilla.xamarin.com/show_bug.cgi?id=49097 --- .../Tasks/CompileEntitlementsTaskBase.cs | 55 +++++++++++++++++-- .../Tasks/EmbedMobileProvisionTaskBase.cs | 10 +++- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileEntitlementsTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileEntitlementsTaskBase.cs index 2cf22c31e818..f79421c164ed 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileEntitlementsTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileEntitlementsTaskBase.cs @@ -167,11 +167,24 @@ PDictionary MergeEntitlementDictionary (PDictionary dict, MobileProvision profil return result; } + static bool AreEqual (byte[] x, byte[] y) + { + if (x.Length != y.Length) + return false; + + for (int i = 0; i < x.Length; i++) { + if (x[i] != y[i]) + return false; + } + + return true; + } + static void WriteXcent (PObject doc, string path) { var buf = doc.ToByteArray (false); - using (var stream = File.Open (path, FileMode.Create)) { + using (var stream = new MemoryStream ()) { if (AppleSdkSettings.XcodeVersion < new Version (4, 4, 1)) { // write the xcent file with the magic header, length, and the plist var length = Mono.DataConverter.BigEndian.GetBytes ((uint) buf.Length + 8); // 8 = magic.length + magicLen.Length @@ -181,6 +194,21 @@ static void WriteXcent (PObject doc, string path) } stream.Write (buf, 0, buf.Length); + + var src = stream.ToArray (); + bool save; + + // Note: if the destination file already exists, only re-write it if the content will change + if (File.Exists (path)) { + var dest = File.ReadAllBytes (path); + + save = !AreEqual (src, dest); + } else { + save = true; + } + + if (save) + File.WriteAllBytes (path, src); } } @@ -285,6 +313,7 @@ public override bool Execute () PDictionary compiled; PDictionary archived; string path; + bool save; if (!string.IsNullOrEmpty (ProvisioningProfile)) { if ((profile = MobileProvisionIndex.GetMobileProvision (Platform, ProvisioningProfile)) == null) { @@ -327,11 +356,25 @@ public override bool Execute () return false; } - try { - archived.Save (Path.Combine (EntitlementBundlePath, "archived-expanded-entitlements.xcent"), true); - } catch (Exception ex) { - Log.LogError ("Error writing archived-expanded-entitlements.xcent file: {0}", ex.Message); - return false; + path = Path.Combine (EntitlementBundlePath, "archived-expanded-entitlements.xcent"); + + if (File.Exists (path)) { + var plist = PDictionary.FromFile (path); + var src = archived.ToXml (); + var dest = plist.ToXml (); + + save = src != dest; + } else { + save = true; + } + + if (save) { + try { + archived.Save (path, true); + } catch (Exception ex) { + Log.LogError ("Error writing archived-expanded-entitlements.xcent file: {0}", ex.Message); + return false; + } } return !Log.HasLoggedErrors; diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/EmbedMobileProvisionTaskBase.cs b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/EmbedMobileProvisionTaskBase.cs index 6bcc1a192cfd..77aa6a23e88d 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Tasks/EmbedMobileProvisionTaskBase.cs +++ b/msbuild/Xamarin.iOS.Tasks.Core/Tasks/EmbedMobileProvisionTaskBase.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; using System.Linq; using Microsoft.Build.Framework; @@ -39,6 +38,13 @@ public override bool Execute () var embedded = Path.Combine (AppBundleDir, "embedded.mobileprovision"); + if (File.Exists (embedded)) { + var embeddedProfile = MobileProvision.LoadFromFile (embedded); + + if (embeddedProfile.Uuid == profile.Uuid) + return true; + } + Directory.CreateDirectory (AppBundleDir); profile.Save (embedded); From 3d6e538df8082d0d072a129013a524dc7d693e5b Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Thu, 15 Dec 2016 15:03:36 -0500 Subject: [PATCH 2/2] [msbuild] Re-enabled the RebuildExecutable_NoModifications unit test With the fixes to EmbedProvisioningProfile and CompileEntitlements, this unit test now passes. --- .../tests/Xamarin.iOS.Tasks.Tests/TargetTests/TargetTests.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/msbuild/tests/Xamarin.iOS.Tasks.Tests/TargetTests/TargetTests.cs b/msbuild/tests/Xamarin.iOS.Tasks.Tests/TargetTests/TargetTests.cs index c6a7059606b0..88a34d52b24d 100644 --- a/msbuild/tests/Xamarin.iOS.Tasks.Tests/TargetTests/TargetTests.cs +++ b/msbuild/tests/Xamarin.iOS.Tasks.Tests/TargetTests/TargetTests.cs @@ -263,7 +263,6 @@ void OptimizePngs_Core (bool shouldBeDifferent) } [Test] - [Ignore ("This test fails due to bugs in our implementation")] public void RebuildExecutable_NoModifications () { // Put a thread.sleep so that the initial build happens a noticable amount of time after we copy @@ -272,11 +271,11 @@ public void RebuildExecutable_NoModifications () // execution of the test fixture 'setup' method. Thread.Sleep (1000); RunTarget (MonoTouchProject, TargetName.Build); - var timestamps = ExpectedExecutableFiles.ToDictionary (file => file, file => GetLastModified (file)); + var timestamps = Directory.EnumerateFiles (AppBundlePath, "*.*", SearchOption.AllDirectories).ToDictionary (file => file, file => GetLastModified (file)); Thread.Sleep (1000); RunTarget (MonoTouchProject, TargetName.Build); - var newTimestamps = ExpectedExecutableFiles.ToDictionary (file => file, file => GetLastModified (file)); + var newTimestamps = Directory.EnumerateFiles (AppBundlePath, "*.*", SearchOption.AllDirectories).ToDictionary (file => file, file => GetLastModified (file)); foreach (var file in timestamps.Keys) Assert.AreEqual (timestamps [file], newTimestamps [file], "#1: " + file);