private static string GetPreviousReleasedPackage(ManifestData projectPackageInfo, PackageInfo packageInfo)
        {
            var version          = SemVersion.Parse(projectPackageInfo.version);
            var previousVersions = packageInfo.versions.all.Where(v =>
            {
                var prevVersion = SemVersion.Parse(v);
                // ignore pre-release and build tags when finding previous version
                return(prevVersion < version && !(prevVersion.Major == version.Major && prevVersion.Minor == version.Minor && prevVersion.Patch == version.Patch));
            });

            // Find the last version on Production
            string previousVersion = null;

            previousVersions = previousVersions.Reverse();
            foreach (var prevVersion in previousVersions)
            {
                if (Utilities.PackageExistsOnProduction(packageInfo.name + "@" + prevVersion))
                {
                    previousVersion = prevVersion;
                    break;
                }
            }

            if (previousVersion != null)
            {
                try
                {
                    ActivityLogger.Log("Retrieving previous package version {0}", previousVersion);
                    var previousPackageId   = ManifestData.GetPackageId(projectPackageInfo.name, previousVersion);
                    var tempPath            = Path.GetTempPath();
                    var previousPackagePath = Path.Combine(tempPath, "previous-" + previousPackageId);
                    var packageFileName     = Utilities.DownloadPackage(previousPackageId, tempPath);
                    Utilities.ExtractPackage(Path.Combine(tempPath, packageFileName), tempPath, previousPackagePath, projectPackageInfo.name);
                    return(previousPackagePath);
                }
                catch (Exception exception)
                {
                    // Failing to fetch when there is no prior version, which is an accepted case.
                    if ((string)exception.Data["reason"] == "fetchFailed")
                    {
                        EditorUtility.DisplayDialog("Data: " + exception.Message, "Failed", "ok");
                    }
                }
            }

            return(string.Empty);
        }
        public static ManifestData GetManifest(string packagePath)
        {
            Profiler.BeginSample("GetManifest");

            // Start by parsing the package's manifest data.
            var manifestPath = Path.Combine(packagePath, Utilities.PackageJsonFilename);

            if (!File.Exists(manifestPath))
            {
                throw new FileNotFoundException(manifestPath);
            }

            // Read manifest json data, and convert it.
            try
            {
                var textManifestData = File.ReadAllText(manifestPath);

                var parsedManifest = SimpleJsonReader.ReadObject(textManifestData);
                if (parsedManifest == null)
                {
                    throw new ArgumentException("invalid JSON");
                }

                ManifestData manifest = new ManifestData();

                var unmarshallingErrors = new List <UnmarshallingException>();
                manifest = JsonUnmarshaller.GetValue <ManifestData>(parsedManifest, ref unmarshallingErrors);
                manifest.decodingErrors.AddRange(unmarshallingErrors);

                manifest.path      = packagePath;
                manifest.lifecycle = ManifestData.EvaluateLifecycle(manifest.version);

                Profiler.EndSample();

                return(manifest);
            }
            catch (ArgumentException e)
            {
                Profiler.EndSample();
                throw new Exception($"Could not parse json in file {manifestPath} because of: {e}");
            }
        }