private static Version FindHighestDependencyVersion(
            OperationContext context,
            IPackage package,
            ProjectInfo project)
        {
            var dependencies = from dSets in package.DependencySets
                               from d in dSets.Dependencies
                               where context.PackagesUpdatedSoFar.Any(p => p.Id == d.Id)
                               select d;

            Version highestDependencyVersion = null;

            foreach (var d in dependencies)
            {
                // Find version of the dependency package
                NuGetPackageInfo depPackage = context.PackagesUpdatedSoFar.Find(p => p.Id == d.Id);

                string source = depPackage.ProjectInfo?.OutputPath;

                if (source != null)
                {
                    string  assemblyPath = Path.Combine(source, depPackage.ProjectInfo.AssemblyName + ".dll");
                    Version version      = GetAssemblyVersion(assemblyPath);

                    if (highestDependencyVersion == null || version > highestDependencyVersion)
                    {
                        highestDependencyVersion = version;
                    }
                }
            }
            return(highestDependencyVersion);
        }
Example #2
0
        /// <summary>
        /// Adds the new project information.
        /// </summary>
        /// <param name="proj">The project.</param>
        private void AddNewProject(IVsProject proj)
        {
            string guid         = GetProjectGuid(proj);
            string name         = GetProjectName(proj);
            string projectFile  = GetProjectFilePath(proj);
            string assemblyName = GetAssemblyName(proj);
            string fullName     = GetProjectUniqueName(proj);
            string outputPath   = GetProjectOutputPath(name);
            bool   inDebugMode  = IsInDebugMode(proj);

            ProjectInfo project = new ProjectInfo(
                guid, name, projectFile, assemblyName, fullName,
                outputPath, inDebugMode);

            // Find the matching NuGet package to this project
            NuGetPackageInfo package = FindPackageByAssemblyName(assemblyName);

            if (package != null)
            {
                project.NuGetPackage = package;
                package.ProjectInfo  = project;
            }
            project.NuGetPackageReferences = GetPackageReferences(project);

            _projects.TryAdd(project.AssemblyName, project);
        }
        private static async TPL.Task <string> RollbackPackage(
            NuGetPackageInfo packageInfo,
            OperationContext context)
        {
            try
            {
                ProjectInfo project = packageInfo.ProjectInfo;
                await RecoverOldVersionFromArchive(packageInfo, context);

                // TODO: 2017-01 Bnaya, use UpdateNuGetDependencies instead of AddBuildEvents
                //using (await UpdateNuGetDependencies(project, context, context.RecoveredPackages))
                using (AddBuildEvents(project, context, context.RecoveredPackages))
                {
                    if (!await context.Projects.BuildProject(project))
                    {
                        //RemoveBuildEvents(project);
                        return($"Failed to build project {project.Name}");
                    }
                } // RemoveBuildEvents(project);
                context.RecoveredPackages.Add(packageInfo);
                return(null);
            }
            catch (Exception ex)
            {
                return(ex.Message);
            }
        }
        private static void MoveOldVersionToArchive(
            NuGetPackageInfo packageInfo,
            OperationContext context)
        {
            try
            {
                if (!context.ShouldArchiveOldNuGet)
                {
                    return;
                }

                if (!Directory.Exists(context.ArchiveSession))
                {
                    Directory.CreateDirectory(context.ArchiveSession);
                }

                string sourcePackagePath = Path.Combine(packageInfo.RepositoryPath, packageInfo.PackageFileName);
                string targetPackagePath = Path.Combine(context.ArchiveSession, packageInfo.PackageFileName);
                File.Move(sourcePackagePath, targetPackagePath);
            }
            catch (Exception ex)
            {
                throw new Exception(@"Fail to archive old NuGets", ex);
            }
        }
Example #5
0
        private NuGetPackageInfo FindPackageByAssemblyName(
            string assemblyName)
        {
            NuGetPackageInfo package = (from p in _context.PackagesInfo
                                        where p.AssemblyName == assemblyName
                                        select p).FirstOrDefault();

            return(package);
        }
        /// <summary>
        /// Builds (projects) the and update (NuGets).
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="packagesToBuild">The packages to build.</param>
        /// <param name="currentProgress">The current progress.</param>
        private static async TPL.Task <DialogResult> BuildAndUpdate(OperationContext context, List <NuGetPackageInfo> packagesToBuild, GeneralUtils.StatusReporter currentProgress)
        {
            for (int i = 0; i < packagesToBuild.Count; i++)
            {
                currentProgress.Report(i);
                NuGetPackageInfo p = packagesToBuild[i];
                GeneralUtils.ReportStatus($"CurrentPackage = {p.Name}");

                string errorMsg = await UpdateSinglePackage(p, context);

                #region Exception Handling (Abort, Retry, Ignore)

                if (errorMsg != null)
                {
                    string       msg    = $@"Failed to update package {p.Id}. 
Error: {errorMsg}.

{context.RecoveredPackages.Count} NuGet packages have been recovered so far.
{context.PackagesUpdatedSoFar.Count} NuGet packages have been updated so far.

Do you want to rollback the state?
OK:     will try to reset the state to the previous state.
Cancel: will stop the processing and let you fix the problem manually.
        you can retry to update after fixing the problem.";
                    DialogResult option = MessageBox.Show(msg, "Execution Problem", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                    switch (option)
                    {
                    case DialogResult.OK:
                        Rollback(context);
                        return(DialogResult.Abort);

                    //return;
                    //case 4: // Retry
                    //    i--;
                    //    continue;
                    case DialogResult.Cancel:
                        return(DialogResult.Cancel);
                    }
                }

                #endregion // Exception Handling (Abort, Retry, Ignore)
            }

            return(DialogResult.OK);
        }
        /// <summary>
        /// Create and save new NuGet package.
        /// </summary>
        /// <param name="packageInfo">The package information.</param>
        /// <param name="project">The project.</param>
        /// <param name="source">The source.</param>
        /// <param name="destination">The destination.</param>
        /// <param name="preRelease">if set to <c>true</c> [pre release].</param>
        /// <returns></returns>
        private static bool CreateNuGet(
            NuGetPackageInfo packageInfo,
            ProjectInfo project,
            string source,
            string destination,
            bool preRelease,
            OperationContext context)
        {
            IPackage       package = packageInfo.NuGetPackage;
            PackageBuilder builder = new PackageBuilder();

            var manifestFiles = CreateManifestFiles(source, package.GetLibFiles());

            builder.PopulateFiles(source, manifestFiles);

            if (package.GetContentFiles().Any())
            {
                var manifestContentFiles = CreateManifestCotentsFiles(
                    package,
                    destination);
                builder.PopulateFiles("", manifestContentFiles);
            }

            var manifestMetadata = CreateManifestMetadata(package, project, source, destination, preRelease, context);

            if (manifestMetadata == null)
            {
                return(false);
            }

            builder.Populate(manifestMetadata);

            var packageName = $"{package.Id}.{manifestMetadata.Version}.nupkg";

            packageInfo.NewPackageName = packageName;
            string packageFile = Path.Combine(destination, packageName);

            using (FileStream stream = File.Open(packageFile, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
            {
                builder.Save(stream);
            }
            return(true);
        }
        private static async void Rollback(
            OperationContext context)
        {
            // Recover the old packages
            for (int i = 0; i < context.PackagesUpdatedSoFar.Count; i++)
            {
                NuGetPackageInfo p = context.PackagesUpdatedSoFar[i];
                GeneralUtils.ReportStatus($"Rollback: {p.Name}");

                string errorMsg = await RollbackPackage(p, context);

                if (errorMsg != null)
                {
                    string       msg    = $@"Failed to recover package {p.Id}. Error: {errorMsg}.
{context.RecoveredPackages.Count} NuGet packages have been recovered so far.
Choose one of the following actions: 
    Abort:  to stop the process
            (you can repeat the process after fixing the problem).
    Ignore: to continue recovering the other packages
    Retry:  to try again (from current stage).";
                    DialogResult option = MessageBox.Show(msg, "Rollback",
                                                          MessageBoxButtons.AbortRetryIgnore,
                                                          MessageBoxIcon.Question,
                                                          MessageBoxDefaultButton.Button1);
                    switch (option)
                    {
                    case DialogResult.Abort:
                        return;

                    case DialogResult.Retry:
                        i--;
                        continue;

                    case DialogResult.Ignore:
                        continue;
                    }
                }
            }
            Directory.Delete(context.ArchiveSession);
            GeneralUtils.ShowMessage($"{context.RecoveredPackages.Count} NuGet packages have been restored");
        }
        private static TPL.Task RecoverOldVersionFromArchive(
            NuGetPackageInfo packageInfo,
            OperationContext context)
        {
            GeneralUtils.ReportStatus($"Recover old version from archive");

            return(TPL.Task.Factory.StartNew(() =>
            {
                string sourcePackagePath = Path.Combine(context.ArchiveSession, packageInfo.PackageFileName);
                string targetPackagePath = Path.Combine(packageInfo.RepositoryPath, packageInfo.PackageFileName);

                if (File.Exists(sourcePackagePath))
                {
                    File.Move(sourcePackagePath, targetPackagePath);
                }

                // Delete the new version from the repository
                string newPackagePath = Path.Combine(packageInfo.RepositoryPath, packageInfo.NewPackageName);
                if (File.Exists(newPackagePath))
                {
                    File.Delete(newPackagePath);
                }
            }, TPL.TaskCreationOptions.LongRunning));
        }
        /// <summary>
        /// Updates the Single package.
        /// </summary>
        /// <param name="packageInfo">The package information.</param>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        private static async TPL.Task <string> UpdateSinglePackage(
            NuGetPackageInfo packageInfo,
            OperationContext context)
        {
            try
            {
                #region Build Project
                ProjectInfo project  = packageInfo.ProjectInfo;
                string      errorMsg = VerifyProjectReadyForUpgrade(project);
                if (errorMsg != null)
                {
                    return(errorMsg);
                }

                // TODO: 2017-01 Bnaya, use UpdateNuGetDependencies instead of AddBuildEvents
                using (await UpdateNuGetDependencies(project, context, context.PackagesUpdatedSoFar))
                //using (AddBuildEvents(project, context, context.PackagesUpdatedSoFar))
                {
                    if (!await context.Projects.BuildProject(project))
                    {
                        //RemoveBuildEvents(project);
                        return($@"Failed to build project {project.Name}

if this project is not a Hosting
set all of its reference to [copy local = false].");
                    }

                    project.ProjectBuilt = true;
                } // RemoveBuildEvents(project);

                #endregion // Build Project

                // source is for the project build files
                string source = project.OutputPath;

                string asmPath = Path.Combine(source, project.AssemblyName + ".dll");
                if (File.Exists(asmPath))
                {
                    var asm = Assembly.ReflectionOnlyLoadFrom(asmPath);
                    if (asm.GetName().Version.ToString() == packageInfo.NuGetPackage.Version.Version.ToString())
                    {
                        context.PackagesUpdatedSoFar.Add(packageInfo);
                        return(null);
                    }
                }

                // destination is for the NuGet packages repository
                string destination = packageInfo.RepositoryPath;

                // create a new NuGet package (we need to keep the old version to allow the update
                // of the NuGet version in the project references)
                if (!CreateNuGet(packageInfo, project, source, destination, context.PreRelease, context))
                {
                    return("Assembly version must increase before the process");
                }

                MoveOldVersionToArchive(packageInfo, context);

                context.PackagesUpdatedSoFar.Add(packageInfo);

                return(null);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
                //GeneralUtils.ShowMessage($"Failed to update package", OLEMSGICON.OLEMSGICON_CRITICAL);
                return(ex.ToString());
            }
        }