private static void ProcessPackage(Packages value, ErrorReporting reporting)
		{
			// Check for an empty file, where no resources/assets are listed.
			if (value.Count <= 0)
			{
				reporting.AddWarning("Package contains 0 assets");
			}

			// Check that duplicate paths are reported as warnings.
			value
				.Select(
					s =>
					new
					{
						Package = s.Key,
						Dupes = value[s.Key].Duplicates().ToList()
					})
				.Where(s => s.Dupes.Count > 0)
				.ToList()
				.ForEach(
					s =>
					reporting.AddWarning(
						string.Format("Package: {0} contains a duplicate asset paths:\n {1}",
							s.Package,
							string.Join("\n\t", s.Dupes.ToArray()))));

			// Check for infinite recursive includes of packages.
		}
		public PackageProcessing(IPathResolver resolver, Packages packages)
		{
			Reporting = new ErrorReporting();

			// Process after setting up Info, Warn, and Errs
			ProcessPackage(packages, Reporting);

			Content = new ContentProvider(resolver, Reporting);

			Packages = ProcessPackageReferences(packages, Reporting, new HashSet<string>());
		}
		private static Packages ProcessPackageReferences(
			Packages packages,
			ErrorReporting reporting,
			HashSet<string> packagesProcessedAlready)
		{
			return
			packages.ToDictionary(
				s => s.Key,
				s =>
				ExpandAssets(s.Key, packages, null, reporting)
					.Distinct()
					.ToList());
		}
		/// <summary>
		/// Reads the given file from disk if it exists, otherwise it logs an error,
		/// and returns an empty string.
		/// </summary>
		/// <param name="filename">
		/// Path to a text file containing an asset's text.
		/// </param>
		/// <param name="reporting">
		/// Error collecting class.
		/// </param>
		/// <returns>
		/// The contents of the file, or empty string.
		/// </returns>
		private string ReadContent(string filename, ErrorReporting reporting)
		{
			if (File.Exists(filename))
			{
				return File.ReadAllText(filename);
			}

			var fn = Resolver.ResolvePath(filename);

			if (File.Exists(fn))
			{
				return File.ReadAllText(fn);
			}

			// Have a filename that doesn't exist, so we log it as an error.
			reporting.AddError(
				string.Format("Could not find file: {0}", filename));

			return "";
		}
		private static IEnumerable<string> ExpandAssets(
			string referencingFile,
			Packages packages,
			HashSet<string> alreadyExpanded,
			ErrorReporting reporting)
		{
			return
			packages.ContainsKey(referencingFile)
				? packages[referencingFile]
					.SelectMany(
						packageFile =>
						packageFile.EndsWith(".package")
							? ExpandPackage(
								referencingFile,
								packageFile,
								packages,
								alreadyExpanded ?? new HashSet<string> { referencingFile },
								reporting)
							: IncludeAsset(packageFile))
				: new List<string>();
		}
		/// <summary>
		/// Given that s is a .package path this will return the list of files
		/// for that package after recursively expanding that .package file.
		/// </summary>
		/// <param name="referencingFile">
		/// The package where this the assetFile is referenced.
		/// </param>
		/// <param name="packageFile">
		/// A .package file.
		/// </param>
		/// <param name="packages">
		/// The set of packages being processed.
		/// </param>
		/// <returns>
		/// List of assets for the package s, where every .package has been expanded.
		/// </returns>
		private static IEnumerable<string> ExpandPackage(
			string referencingFile,
			string packageFile,
			Packages packages,
			HashSet<string> alreadyExpanded,
			ErrorReporting reporting)
		{
			// Have 2 cases:
			//	case 1: packages contains reference.
			//	case 2: packages DOES NOT contain reference.
			if (packages.ContainsKey(packageFile))
			{
				if (alreadyExpanded.Contains(packageFile))
				{
					reporting.AddError(
						string.Format(
						"Already included package:"
						+ "\n\t{0} and including it again would cause infinite recursion."
						+ "\n\tNo further expansion done.",
						packageFile));

					return new List<string>();
				}
				else
				{
					alreadyExpanded.Add(packageFile);

					return ExpandAssets(packageFile, packages, alreadyExpanded, reporting);
				}
			}
			else
			{
				reporting.AddWarning(
					string.Format(
					"Could not find package: {0}, as referenced in {1}",
					packageFile,
					referencingFile));
					
				return new List<string>();
			}
		}
		public ContentProvider(IPathResolver resolver, ErrorReporting reporting)
		{
			Content = new Dictionary<string, string>();
			Resolver = resolver;
			Reporting = reporting;
		}