#!/usr/bin/env /Library/Frameworks/Mono.framework/Commands/csharp using System.Diagnostics; using System.IO; var args = Environment.GetCommandLineArgs (); // first arg is "/Library/Frameworks/Mono.framework/Versions/4.8.0/lib/mono/4.5/csharp.exe" // second arg the script itself // then comes the ones we care about: the date and the number of weeks if (args.Length < 5) { Console.WriteLine ("Usage: ./xcode-diff.csharp /path/to/base/xcode.app /path/to/new/xcode.app output-subdirectory"); Environment.Exit (1); } // old Xcode did not have a symlink to the latest SDK and could have multiple SDK for simulator var old_xcode = args [2]; if (!Directory.Exists (old_xcode)) { Console.WriteLine ("Cannot find {0}", old_xcode); Environment.Exit (1); } var new_xcode = args [3]; if (new_xcode.IndexOf (".platform", StringComparison.Ordinal) < 0) { Console.WriteLine ("Directory precision mismatch, either provide Xcode paths (for iOS) or specific Frameworks directories for both Xcode targets"); Environment.Exit (1); } var output_dir = args [4]; var unsupportedFrameworks = args.Skip (5).ToHashSet (); // unique name: {xcode}/{beta}/{platform}/{framework}-{platform}-{xcode}-{beta}.md var split = output_dir.Split (new char [] { '/' }, StringSplitOptions.RemoveEmptyEntries); var l = split.Length; var fileSuffix = $"-{split [l - 1]}-{split [l - 3]}-{split [l - 2]}.md"; if (!Directory.Exists (new_xcode)) { Console.WriteLine ("Cannot find {0}", new_xcode); Environment.Exit (1); } var collect = new Func> ((directory) => { var list = new SortedList (); foreach (var fx in Directory.EnumerateDirectories (directory, "*.framework", SearchOption.AllDirectories)) { var headers = Path.Combine (fx, "Headers"); if (!Directory.Exists (headers)) continue; var name = Path.GetFileName (fx); var nameOnly = Path.GetFileNameWithoutExtension (name); if (unsupportedFrameworks.Contains (nameOnly)) continue; // of course macOS use symlinks to duplicate :( if (list.ContainsKey (name)) continue; list.Add (name, headers); } return list; }); var differ = new Action ((fx_name, old_headers, new_headers) => { var diff = $"#{fx_name}\n\n"; diff += "``` diff\n"; var info = new ProcessStartInfo ("diff", $"-ruN {old_headers} {new_headers}"); info.RedirectStandardOutput = true; info.UseShellExecute = false; var p = Process.Start (info); var output = p.StandardOutput.ReadToEnd (); diff += output; p.WaitForExit (); if (p.ExitCode == 0 || string.IsNullOrEmpty (output)) return; diff += "\n```"; var fx_short_name = fx_name.Remove (fx_name.IndexOf ('.')); var file = new FileInfo (Path.Combine (output_dir, $"{fx_short_name}{fileSuffix}")); file.Directory.Create (); File.WriteAllText (file.FullName, diff); }); var old_fx = collect (old_xcode); var new_fx = collect (new_xcode); foreach (var fx in old_fx) { if (new_fx.TryGetValue (fx.Key, out var directory)) { // diff old and new differ (fx.Key, fx.Value, directory); new_fx.Remove (fx.Key); } else { // fx was removed var dummy = fx.Value.Replace (old_xcode, new_xcode); differ (fx.Key, fx.Value, dummy); } } // diff remaining new frameworks foreach (var fx in new_fx) { var dummy = fx.Value.Replace (new_xcode, old_xcode); differ (fx.Key, dummy, fx.Value); } Environment.Exit (0);