internal static Task<PackageFeed> GetPackageFeedFromLocation(string location, bool recursive = false) { return Recognizer.Recognize(location, ensureLocal: true).ContinueWithParent(antecedent => { var info = antecedent.Result; PackageFeed result = null; string locationKey = null; if (info.IsPackageFeed) { if (info.IsFolder) { locationKey = Path.Combine(info.FullPath, info.Wildcard ?? "*"); if (AllFeeds.ContainsKey(locationKey)) { return AllFeeds[locationKey]; } result = new DirectoryPackageFeed(info.FullPath, info.Wildcard, recursive); } else if (info.IsFile) { if (AllFeeds.ContainsKey(info.FullPath)) { return AllFeeds[info.FullPath]; } if (info.IsAtom) { result = new AtomPackageFeed(info.FullPath); } if (info.IsArchive) { result = new ArchivePackageFeed(info.FullPath); } } // TODO: URL based feeds else if (info.IsURL) { if (AllFeeds.ContainsKey(info.FullUrl.AbsoluteUri)) { return AllFeeds[info.FullUrl.AbsoluteUri]; } if (info.IsAtom) { result = new AtomPackageFeed(info.FullUrl); } } } if (result != null) { result.RecognitionInfo = info; lock (AllFeeds) { if (!AllFeeds.ContainsKey(locationKey ?? result.Location)) { AllFeeds.Add(locationKey ?? result.Location, result); } else result = AllFeeds[locationKey ?? result.Location]; // GS01: TODO: This is a crappy way of avoiding a deadlock when the same feed has been requested twice by two different threads. } } return result; }); }
/// <summary> /// Gets the package feed from the location. /// /// This will first attempt to look up a matching instance in the AllFeeds collection (so that multiple requests for the same feed return a single object) /// /// It asks the recognizer to identify the location, and creates a specific subclass instance based on the results. /// /// If it cannot identify or read the target, the task will return null. /// </summary> /// <param name="location">The feed location (url, file, directory).</param> /// <returns>A Task with a return value of the PackageFeed. May be null if invalid.</returns> /// <remarks></remarks> internal static Task<PackageFeed> GetPackageFeedFromLocation(string location) { if( InstalledPackageFeed.CanonicalLocation.Equals(location, StringComparison.CurrentCultureIgnoreCase)) { return Task<PackageFeed>.Factory.StartNew(() => InstalledPackageFeed.Instance).AutoManage(); } if( SessionPackageFeed.CanonicalLocation.Equals(location, StringComparison.CurrentCultureIgnoreCase)) { return Task<PackageFeed>.Factory.StartNew(() => SessionPackageFeed.Instance).AutoManage(); } return Recognizer.Recognize(location).ContinueWith(antecedent => { var info = antecedent.Result; PackageFeed result = null; string locationKey = null; if (info.IsPackageFeed) { if (info.IsFolder) { locationKey = Path.Combine(info.FullPath, info.Filter ); if (_allFeeds.ContainsKey(locationKey)) { return _allFeeds[locationKey]; } result = new DirectoryPackageFeed(info.FullPath, info.Filter); } else if (info.IsFile) { if (_allFeeds.ContainsKey(info.FullPath)) { return _allFeeds[info.FullPath]; } if (info.IsAtom) { result = new AtomPackageFeed(info.FullPath); } /* if (info.IsArchive) { result = new ArchivePackageFeed(info.FullPath); } * */ } // TODO: URL based feeds else if (info.IsURL) { if (_allFeeds.ContainsKey(info.FullUrl.AbsoluteUri)) { return _allFeeds[info.FullUrl.AbsoluteUri]; } if (info.IsAtom) { result = new AtomPackageFeed(info.FullUrl); } } } else if(info.IsPackageFile) { // SessionPackageFeed.Instance.Add(Package.GetPackageFromFilename(info.FullPath)); result = new DirectoryPackageFeed(Path.GetDirectoryName(info.FullPath),Path.GetFileName(info.FullPath)); // Hack of the day: // Since, I have to look up this file as a feed again later, based on the original path (likely, an http:// location) // we have to forcably set the location in the feed itself to reflect this. result.Location = location; locationKey = location; } if (result != null) { result.RecognitionInfo = info; lock (_allFeeds) { if (!_allFeeds.ContainsKey(locationKey ?? result.Location)) { _allFeeds.Add(locationKey ?? result.Location, result); } else { result = _allFeeds[locationKey ?? result.Location]; } // GS01: TODO: This is a crappy way of avoiding a deadlock when the same feed has been requested twice by two different threads. } } return result; }, TaskContinuationOptions.AttachedToParent ); }