Welcome to mirror list, hosted at ThFree Co, Russian Federation.

AppleDocHandler.cs - github.com/xamarin/macdoc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b5f1f687b9e7d45829cb3ee640f0b5dca2781219 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.IO;
using System.Net;
using System.Linq;
using System.Threading;
using System.Xml.Linq;

namespace macdoc
{
	public class AppleDocHandler
	{
		public class AppleDocInformation
		{
			public Version Version { get; set; }
			public string ID { get; set; }
			public DateTime UpdateDate { get; set; }
			public string DownloadUrl { get; set; }
		}
		
		readonly string[] searchPaths = new[] {
			"/Applications/Xcode.app/Contents/Developer/Documentation/DocSets/",
			"/Library/Developer/Shared/Documentation/DocSets/",
			"/Developer/Platforms/iPhoneOS.platform/Developer/Documentation/DocSets/"
		};
		const string MonodocLibPath = "/Library/Frameworks/Mono.framework/External/monodoc/";
		const string MonoTouchLibPath = "/Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll";

		public const string Ios5AtomFeed = "https://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone5_0.atom";
		public const string Ios6AtomFeed = "https://developer.apple.com/rss/com.apple.adc.documentation.AppleiPhone6.0.atom";
		public const string MacLionAtomFeed = "http://developer.apple.com/rss/com.apple.adc.documentation.AppleLion.atom";
		public const string MacMountainLionFeed = "https://developer.apple.com/rss/com.apple.adc.documentation.AppleOSX10_8.atom";

		readonly XNamespace docsetNamespace = "http://developer.apple.com/rss/docset_extensions";
		readonly XNamespace atomNamespace = "http://www.w3.org/2005/Atom";
		readonly string baseApplicationPath;

		XDocument appleFeed;
		
		public AppleDocHandler (string baseApplicationPath)
		{
			this.baseApplicationPath = baseApplicationPath;
		}
		
		// We load the atom field that contains a timeline of the modifications down to documentation by Apple
		XDocument LoadAppleFeed (string feedUrl)
		{
			if (appleFeed != null)
				return appleFeed;
			
			WebClient wc = new WebClient ();
			var feed = wc.DownloadString (feedUrl);
			return appleFeed = XDocument.Parse (feed);
		}

		// This method transforms the Atom XML data into a POCO for the the most recent item of the feed
		AppleDocInformation GetLatestAppleDocInformation (XDocument feed)
		{
			var latestEntry = feed.Descendants (atomNamespace + "entry").LastOrDefault ();
			if (latestEntry == null)
				return null;
			
			var infos = new AppleDocInformation () {
				Version = CloneFillWithZeros (new Version (latestEntry.Element (docsetNamespace + "version").Value)),
				ID = latestEntry.Element (docsetNamespace + "identifier").Value,
				UpdateDate = DateTime.Parse (latestEntry.Element (atomNamespace + "updated").Value),
				DownloadUrl = latestEntry.Element (atomNamespace + "link").Attribute ("href").Value
			};

			return infos;
		}

		// This method read the Info.plist available in all Apple .docset to get the version of the bundle
		Version GetAppleDocVersion (string directory)
		{
			var plist = Path.Combine (directory, "Contents", "Info.plist");
			if (!File.Exists (plist))
				return null;

			var doc = XDocument.Load (plist);
			var version = doc.Descendants ("key")
				.First (k => k.Value.Equals ("CFBundleVersion", StringComparison.Ordinal))
				.ElementsAfterSelf ()
				.First ()
				.Value;

			return CloneFillWithZeros (new Version (version));
		}

		// This method checks that an iOS documentation set is installed on the user machine
		// and also checks if it's the latest available
		bool CheckAppleDocAvailabilityAndFreshness (AppleDocInformation infos)
		{
			var path = searchPaths
				.Select (p => Path.Combine (p, infos.ID + ".docset"))
				.FirstOrDefault (p => Directory.Exists (p));

			if (path == null)
				return false;

			var installedVersion = GetAppleDocVersion (path);
			return installedVersion >= infos.Version;
		}

		// atom feed is one of the Apple documentation feed, iOS and Lion are given in const form above
		// returns true if the documentation was updated, false otherwise. The progressDelegate parameter
		// is given the completion percentage
		public bool CheckAppleDocFreshness (string atomFeed, out AppleDocInformation infos)
		{
			var feed = LoadAppleFeed (atomFeed);
			infos = GetLatestAppleDocInformation (feed);
			var needRefresh = !CheckAppleDocAvailabilityAndFreshness (infos);
			
			return needRefresh;
		}
		
		public bool CheckMergedDocumentationFreshness (AppleDocInformation infos, Product product)
		{
			var statusFile = Path.Combine (baseApplicationPath, "macdoc");
			if (!Directory.Exists (statusFile)) {
				try {
					Directory.CreateDirectory (statusFile);
				} catch {}
				return true;
			}
			statusFile = Path.Combine (statusFile, product == Product.MonoMac ? "merge.mac.status" : "merge.status");
			if (!File.Exists (statusFile))
				return true;
			if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("APPLEDOCWIZARD_FORCE_MERGE")))
				return true;
			
			var mergedVersion = CloneFillWithZeros (new Version (File.ReadAllText (statusFile)));
			return mergedVersion != infos.Version;
		}
		
		static Version CloneFillWithZeros (Version v)
		{
			if (v == null)
				return null;
			int major = v.Major == -1 ? 0 : v.Major;
			int minor = v.Minor == -1 ? 0 : v.Minor;
			int build = v.Build == -1 ? 0 : v.Build;
			int revision = v.Revision == -1 ? 0 : v.Revision;

			return new Version (major, minor, build, revision);
		}

	}
}