public string DiscoverExistingPackagePath(string moduleRoot, PackageRef package, string platform)
        {
            var redirectedUri = _packageRedirector.RedirectPackageUrl(package.Uri);

            if (redirectedUri.StartsWith("local-pointer://", StringComparison.InvariantCultureIgnoreCase))
            {
                // This is a locally redirected package, where the redirect goes straight to another folder
                // on the local computer (alternatively local-git:// will still clone from the target
                // folder, while this allows you to work on the target folder directly).
                return(redirectedUri.Substring("local-pointer://".Length));
            }

            // Check the ModuleInfo.xml files of other modules in the
            // hierarchy in this order:
            // * Above us (this ensures the common libraries are at the highest point)
            // * Across from us (in the same folder) up to our name alphabetically
            // * Below us

            bool isNestedInPlatformFolder;
            var  parentModule = this.GetParentModule(moduleRoot, platform, out isNestedInPlatformFolder);

            if (parentModule != null)
            {
                var above = this.CheckAbove(parentModule, package, platform);
                if (above != null)
                {
                    return(above);
                }

                var directoryName = new DirectoryInfo(moduleRoot).Name;
                if (isNestedInPlatformFolder)
                {
                    directoryName = new DirectoryInfo(Path.Combine(moduleRoot, "..")).Name;
                }

                var across = this.CheckAcross(parentModule, package, directoryName, platform);
                if (across != null)
                {
                    return(across);
                }
            }

            return(null);
        }
        public IPackageMetadata Lookup(PackageRequestRef request)
        {
            request.Uri = _packageRedirector.RedirectPackageUrl(request.Uri);

            if (request.Uri.StartsWith("local-pointer://", StringComparison.InvariantCultureIgnoreCase))
            {
                throw new InvalidOperationException("local-pointer:// URIs should never reach this section of code.");
            }

            IPackageMetadata metadata = null;
            var schemeFound           = false;

            foreach (var protocol in _packageProtocols)
            {
                foreach (var scheme in protocol.Schemes)
                {
                    if (request.Uri.StartsWith(scheme + "://"))
                    {
                        schemeFound = true;
                        metadata    = protocol.ResolveSource(request);
                        break;
                    }
                }

                if (schemeFound)
                {
                    break;
                }
            }

            if (!schemeFound)
            {
                throw new InvalidOperationException("Unknown package protocol scheme for URI: " + request.Uri);
            }

            if (schemeFound && metadata == null)
            {
                throw new InvalidOperationException("Package resolution failed to complete successfully");
            }

            return(metadata);
        }
        public void Lookup(
            string uri,
            string platform,
            bool preferCacheLookup,
            out string sourceUri,
            out string type,
            out Dictionary <string, string> downloadMap,
            out Dictionary <string, string> archiveTypeMap,
            out Dictionary <string, string> resolvedHash)
        {
            uri = _packageRedirector.RedirectPackageUrl(uri);

            if (uri.StartsWith("local-git://", StringComparison.InvariantCultureIgnoreCase))
            {
                sourceUri      = uri.Substring("local-git://".Length);
                type           = PackageManager.PACKAGE_TYPE_LIBRARY;
                downloadMap    = new Dictionary <string, string>();
                archiveTypeMap = new Dictionary <string, string>();
                resolvedHash   = new Dictionary <string, string>();
                return;
            }

            if (uri.StartsWith("http-git://", StringComparison.InvariantCultureIgnoreCase))
            {
                sourceUri      = "http://" + uri.Substring("http-git://".Length);
                type           = PackageManager.PACKAGE_TYPE_LIBRARY;
                downloadMap    = new Dictionary <string, string>();
                archiveTypeMap = new Dictionary <string, string>();
                resolvedHash   = new Dictionary <string, string>();
                return;
            }

            if (uri.StartsWith("https-git://", StringComparison.InvariantCultureIgnoreCase))
            {
                sourceUri      = "https://" + uri.Substring("https-git://".Length);
                type           = PackageManager.PACKAGE_TYPE_LIBRARY;
                downloadMap    = new Dictionary <string, string>();
                archiveTypeMap = new Dictionary <string, string>();
                resolvedHash   = new Dictionary <string, string>();
                return;
            }

            var baseUri = new Uri(uri);

            var     apiUri  = new Uri(baseUri.ToString().TrimEnd('/') + "/api");
            dynamic apiData = null;

            var performOnlineLookup = true;

            if (preferCacheLookup)
            {
                performOnlineLookup = false;
                if (File.Exists(this.GetLookupCacheFilename(uri)))
                {
                    try
                    {
                        using (var reader = new StreamReader(this.GetLookupCacheFilename(uri)))
                        {
                            apiData = JSON.ToDynamic(reader.ReadToEnd());
                        }
                    }
                    catch (ExecEnvironment.SelfInvokeExitException)
                    {
                        throw;
                    }
                    catch
                    {
                        performOnlineLookup = true;
                    }
                }
                else
                {
                    performOnlineLookup = true;
                }
            }

            if (performOnlineLookup)
            {
                try
                {
                    string jsonString;
                    apiData = this.GetJSON(apiUri, out jsonString);
                    if (apiData.has_error)
                    {
                        throw new InvalidOperationException((string)apiData.error);
                    }
                    using (var writer = new StreamWriter(this.GetLookupCacheFilename(uri)))
                    {
                        writer.Write(jsonString);
                    }
                }
                catch (WebException)
                {
                    // Attempt to retrieve it from the lookup cache.
                    if (File.Exists(this.GetLookupCacheFilename(uri)))
                    {
                        var shouldThrow = false;
                        try
                        {
                            using (var reader = new StreamReader(this.GetLookupCacheFilename(uri)))
                            {
                                apiData = JSON.ToDynamic(reader.ReadToEnd());
                            }
                        }
                        catch (ExecEnvironment.SelfInvokeExitException)
                        {
                            throw;
                        }
                        catch
                        {
                            shouldThrow = true;
                        }
                        if (shouldThrow)
                        {
                            throw;
                        }
                    }
                    else
                    {
                        throw;
                    }
                }
                catch (InvalidOperationException)
                {
                    // Attempt to retrieve it from the lookup cache.
                    if (File.Exists(this.GetLookupCacheFilename(uri)))
                    {
                        var shouldThrow = false;
                        try
                        {
                            using (var reader = new StreamReader(this.GetLookupCacheFilename(uri)))
                            {
                                apiData = JSON.ToDynamic(reader.ReadToEnd());
                            }
                        }
                        catch (ExecEnvironment.SelfInvokeExitException)
                        {
                            throw;
                        }
                        catch
                        {
                            shouldThrow = true;
                        }
                        if (shouldThrow)
                        {
                            throw;
                        }
                    }
                    else
                    {
                        throw;
                    }
                }
            }

            if (apiData == null)
            {
                throw new InvalidOperationException("apiData is null");
            }

            sourceUri = (string)apiData.result.package.gitUrl;
            type      = (string)apiData.result.package.type;

            if (!string.IsNullOrWhiteSpace(sourceUri))
            {
                try
                {
                    new Uri(sourceUri);
                }
                catch (ExecEnvironment.SelfInvokeExitException)
                {
                    throw;
                }
                catch
                {
                    throw new InvalidOperationException(
                              "Received invalid Git URL when loading package from " + apiUri);
                }
            }
            else
            {
                Console.WriteLine("WARNING: This package does not have a source repository set.");
            }

            downloadMap    = new Dictionary <string, string>();
            archiveTypeMap = new Dictionary <string, string>();
            resolvedHash   = new Dictionary <string, string>();
            foreach (var ver in apiData.result.versions)
            {
                if (ver.platformName != platform)
                {
                    continue;
                }
                if (!downloadMap.ContainsKey(ver.versionName))
                {
                    downloadMap.Add(ver.versionName, ver.downloadUrl);
                    archiveTypeMap.Add(ver.versionName, ver.archiveType);
                    resolvedHash.Add(ver.versionName, ver.versionName);
                }
            }
            foreach (var branch in apiData.result.branches)
            {
                if (!downloadMap.ContainsKey(branch.versionName))
                {
                    continue;
                }
                if (!downloadMap.ContainsKey(branch.branchName))
                {
                    downloadMap.Add(branch.branchName, downloadMap[branch.versionName]);
                    archiveTypeMap.Add(branch.branchName, archiveTypeMap[branch.versionName]);
                    resolvedHash.Add(branch.branchName, branch.versionName);
                }
            }
        }