protected override ProjectUpgradeState UpgradeProjectCheck(ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action<__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport) { var envVarsProp = projectXml.Properties.FirstOrDefault(p => p.Name == NodejsConstants.EnvironmentVariables); if (envVarsProp != null && !string.IsNullOrEmpty(envVarsProp.Value)) { return ProjectUpgradeState.OneWayUpgrade; } return ProjectUpgradeState.NotNeeded; }
/// <summary> /// Determines whether a project needs to be upgraded. /// </summary> /// <param name="projectXml"> /// The XML of the project file being upgraded. /// </param> /// <param name="userProjectXml"> /// The XML of the user file being upgraded, or null if no user file /// exists. /// </param> /// <param name="log"> /// Callback to log messages. These messages will be added to the /// migration log that is displayed after upgrading completes. /// </param> /// <param name="projectFactory"> /// The project factory that will be used. This may be replaced with /// another Guid if a new project factory should be used to upgrade the /// project. /// </param> /// <param name="backupSupport"> /// The level of backup support requested for the project. By default, /// the project file (and user file, if any) will be copied alongside /// the originals with ".old" added to the filenames. /// </param> /// <returns> /// The form of upgrade required. /// </returns> protected virtual ProjectUpgradeState UpgradeProjectCheck( ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action <__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport ) { return(ProjectUpgradeState.NotNeeded); }
protected override ProjectUpgradeState UpgradeProjectCheck( ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action <__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport ) { Version version; // Web projects are incompatible with WDExpress/Shell ProjectPropertyElement projectType; if (!IsWebProjectSupported && (projectType = projectXml.Properties.FirstOrDefault(p => p.Name == "ProjectTypeGuids")) != null) { var webProjectGuid = new Guid(PythonConstants.WebProjectFactoryGuid); if (projectType.Value .Split(';') .Select(s => { Guid g; return(Guid.TryParse(s, out g) ? g : Guid.Empty); }) .Contains(webProjectGuid) ) { log(__VSUL_ERRORLEVEL.VSUL_ERROR, SR.GetString(SR.ProjectRequiresVWDExpress)); return(ProjectUpgradeState.Incompatible); } } var imports = new HashSet <string>(projectXml.Imports.Select(p => p.Project), StringComparer.OrdinalIgnoreCase); // Importing a targets file from 2.1 Beta if (imports.Contains(Ptvs21BetaBottleTargets) || imports.Contains(Ptvs21BetaFlaskTargets)) { return(ProjectUpgradeState.SafeRepair); } // Only importing the Common targets and/or props. if (imports.Contains(CommonProps) || imports.Contains(CommonTargets) && imports.Count == 1) { return(ProjectUpgradeState.OneWayUpgrade); } // ToolsVersion less than 4.0 (or unspecified) is not supported, so // set it to 4.0. if (!Version.TryParse(projectXml.ToolsVersion, out version) || version < new Version(4, 0)) { return(ProjectUpgradeState.SafeRepair); } return(ProjectUpgradeState.NotNeeded); }
protected override ProjectUpgradeState UpgradeProjectCheck( ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action <__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport ) { Version version; // Referencing an interpreter by GUID if (projectXml.Properties.Where(p => p.Name == "InterpreterId").Any(IsGuidValue) || projectXml.ItemGroups.SelectMany(g => g.Items) .Where(i => i.ItemType == "InterpreterReference") .Any(IsGuidValue) || projectXml.ItemGroups.SelectMany(g => g.Items) .Where(i => i.ItemType == "Interpreter") .SelectMany(i => i.Metadata.Where(m => m.Name == "BaseInterpreter")) .Any(IsGuidValue) ) { return(ProjectUpgradeState.OneWayUpgrade); } // Includes imports from PTVS 2.2 if (projectXml.Properties.Any(IsPtvsTargetsFileProperty)) { return(ProjectUpgradeState.SafeRepair); } var imports = new HashSet <string>(projectXml.Imports.Select(p => p.Project), StringComparer.OrdinalIgnoreCase); // Importing a targets file from 2.1 Beta if (imports.Contains(Ptvs21BetaBottleTargets) || imports.Contains(Ptvs21BetaFlaskTargets)) { return(ProjectUpgradeState.SafeRepair); } // Only importing the Common targets and/or props. if (imports.Contains(CommonProps) || imports.Contains(CommonTargets) && imports.Count == 1) { return(ProjectUpgradeState.OneWayUpgrade); } // ToolsVersion less than 4.0 (or unspecified) is not supported, so // set it to 4.0. if (!Version.TryParse(projectXml.ToolsVersion, out version) || version < new Version(4, 0)) { return(ProjectUpgradeState.SafeRepair); } return(ProjectUpgradeState.NotNeeded); }
protected override ProjectUpgradeState UpgradeProjectCheck( ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action <__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport ) { Version version; if (!Version.TryParse(projectXml.ToolsVersion, out version) || version < new Version(4, 0)) { return(ProjectUpgradeState.SafeRepair); } return(ProjectUpgradeState.NotNeeded); }
private int NormalizeUpgradeFlag(uint upgradeFlag, out __VSPPROJECTUPGRADEVIAFACTORYFLAGS flag, ref string copyLocation) { flag = (__VSPPROJECTUPGRADEVIAFACTORYFLAGS)upgradeFlag; // normalize flags switch (flag) { case __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP: case __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP: break; default: // ignore unknown flags flag &= (__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP); break; } //if copy upgrade, then we need a copy location that ends in a backslash. if (HasCopyBackupFlag(flag)) { if (string.IsNullOrEmpty(copyLocation) || copyLocation[copyLocation.Length - 1] != '\\') { if (HasSxSBackupFlag(flag)) { //if both SxS AND CopyBack were specified, then fall back to SxS flag &= ~__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP; } else { //Only CopyBackup was specified and an invalid backup location was given, so bail return(VSConstants.E_INVALIDARG); } } else { //Favor copy backup to SxS backup flag &= ~__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP; } } return(VSConstants.S_OK); }
/// <summary> /// Helper for checking if flag has PUVFF_COPYBACKUP value /// </summary> private static bool HasCopyBackupFlag(__VSPPROJECTUPGRADEVIAFACTORYFLAGS flag) { return flag.HasFlag(__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP); }
private void BackupProjectFilesIfNeeded( string projectFilePath, ProjectUpgradeLogger logger, __VSPPROJECTUPGRADEVIAFACTORYFLAGS flag, string copyLocation, ProjectRootElement convertedProject ) { var projectName = Path.GetFileNameWithoutExtension(projectFilePath); var projectFileName = Path.GetFileName(projectFilePath); if (HasCopyBackupFlag(flag) || HasSxSBackupFlag(flag)) { if (HasSxSBackupFlag(flag) && !Directory.Exists(copyLocation)) { Debug.Assert(false, "Env should create the directory for us"); throw new ProjectUpgradeFailedException(); } // copy project file { var targetFilePath = Path.Combine(copyLocation, projectFileName); if (HasSxSBackupFlag(flag)) { bool ignored; targetFilePath = GetUniqueFileName(targetFilePath + ".old", out ignored); } try { File.Copy(projectFilePath, targetFilePath); logger.LogInfo(SR.GetString(SR.ProjectBackupSuccessful, targetFilePath)); } catch (Exception ex) { var message = SR.GetString(SR.ErrorMakingProjectBackup, targetFilePath); throw new ProjectUpgradeFailedException(string.Format("{0} : {1}", message, ex.Message)); } } if (HasCopyBackupFlag(flag)) { //Now iterate through the project items and copy them to the new location //All projects under the solution retain its folder hierarchy var types = new[] { "Compile", "None", "Content", "EmbeddedResource", "Resource", "BaseApplicationManifest", "ApplicationDefinition", "Page" }; var metadataLookup = convertedProject .Items .GroupBy(i => i.ItemType) .ToDictionary(x => x.Key); var sourceProjectDir = Path.GetDirectoryName(projectFilePath); foreach (var ty in types) { if (metadataLookup.ContainsKey(ty)) { foreach (var item in metadataLookup[ty]) { var linkMetadataElement = item.Metadata.FirstOrDefault(me => me.Name == "Link"); string linked = linkMetadataElement != null && !string.IsNullOrEmpty(linkMetadataElement.Value) ? linkMetadataElement.Value : null; var include = item.Include; Debug.Assert(!string.IsNullOrEmpty(include)); string sourceFilePath; var targetFileName = Path.Combine(copyLocation, linked ?? include); if (Path.IsPathRooted(include)) { //if the path is fully qualified already, then just use it sourceFilePath = include; } else { //otherwise tack the filename on to the path sourceFilePath = Path.Combine(sourceProjectDir, include); } if (linked != null && include[0] == '.') { //if linked file up a level (or more), then turn it into a path without the ..\ in the middle sourceFilePath = Path.GetFullPath(sourceFilePath); } bool initiallyUnique; targetFileName = GetUniqueFileName(targetFileName, out initiallyUnique); if (!initiallyUnique) { logger.LogInfo(SR.GetString(SR.BackupNameConflict, targetFileName)); } //Warn user in upgrade log if linked files are used "project may not build" if (linked != null && HasCopyBackupFlag(flag)) { logger.LogWarning(SR.GetString(SR.ProjectContainsLinkedFile, targetFileName)); } // ensure target folder exists Directory.CreateDirectory(Path.GetDirectoryName(targetFileName)); try { File.Copy(sourceFilePath, targetFileName); logger.LogInfo(SR.GetString(SR.BackupSuccessful, targetFileName)); } catch (Exception ex) { var message = SR.GetString(SR.ErrorMakingBackup, targetFileName); logger.LogError(string.Format("{0} : {1}", message, ex.Message)); } } } } } } }
private int NormalizeUpgradeFlag(uint upgradeFlag, out __VSPPROJECTUPGRADEVIAFACTORYFLAGS flag, ref string copyLocation) { flag = (__VSPPROJECTUPGRADEVIAFACTORYFLAGS)upgradeFlag; // normalize flags switch (flag) { case __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP: case __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP: break; default: // ignore unknown flags flag &= (__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP | __VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP); break; } //if copy upgrade, then we need a copy location that ends in a backslash. if (HasCopyBackupFlag(flag)) { if (string.IsNullOrEmpty(copyLocation) || copyLocation[copyLocation.Length - 1] != '\\') { if (HasSxSBackupFlag(flag)) { //if both SxS AND CopyBack were specified, then fall back to SxS flag &= ~__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP; } else { //Only CopyBackup was specified and an invalid backup location was given, so bail return VSConstants.E_INVALIDARG; } } else { //Favor copy backup to SxS backup flag &= ~__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_SXSBACKUP; } } return VSConstants.S_OK; }
protected override ProjectUpgradeState UpgradeProjectCheck( ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action<__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport ) { Version version; // Web projects are incompatible with WDExpress/Shell ProjectPropertyElement projectType; if (!IsWebProjectSupported && (projectType = projectXml.Properties.FirstOrDefault(p => p.Name == "ProjectTypeGuids")) != null) { var webProjectGuid = new Guid(PythonConstants.WebProjectFactoryGuid); if (projectType.Value .Split(';') .Select(s => { Guid g; return Guid.TryParse(s, out g) ? g : Guid.Empty; }) .Contains(webProjectGuid) ) { log(__VSUL_ERRORLEVEL.VSUL_ERROR, SR.GetString(SR.ProjectRequiresVWDExpress)); return ProjectUpgradeState.Incompatible; } } var imports = new HashSet<string>(projectXml.Imports.Select(p => p.Project), StringComparer.OrdinalIgnoreCase); // Importing a targets file from 2.1 Beta if (imports.Contains(Ptvs21BetaBottleTargets) || imports.Contains(Ptvs21BetaFlaskTargets)) { return ProjectUpgradeState.SafeRepair; } // Only importing the Common targets and/or props. if (imports.Contains(CommonProps) || imports.Contains(CommonTargets) && imports.Count == 1) { return ProjectUpgradeState.OneWayUpgrade; } // ToolsVersion less than 4.0 (or unspecified) is not supported, so // set it to 4.0. if (!Version.TryParse(projectXml.ToolsVersion, out version) || version < new Version(4, 0)) { return ProjectUpgradeState.SafeRepair; } return ProjectUpgradeState.NotNeeded; }
/// <summary> /// Helper for checking if flag has PUVFF_COPYBACKUP value /// </summary> private static bool HasCopyBackupFlag(__VSPPROJECTUPGRADEVIAFACTORYFLAGS flag) { return(flag.HasFlag(__VSPPROJECTUPGRADEVIAFACTORYFLAGS.PUVFF_COPYBACKUP)); }
private void BackupProjectFilesIfNeeded( string projectFilePath, ProjectUpgradeLogger logger, __VSPPROJECTUPGRADEVIAFACTORYFLAGS flag, string copyLocation, ProjectRootElement convertedProject ) { var projectName = Path.GetFileNameWithoutExtension(projectFilePath); var projectFileName = Path.GetFileName(projectFilePath); if (HasCopyBackupFlag(flag) || HasSxSBackupFlag(flag)) { if (HasSxSBackupFlag(flag) && !Directory.Exists(copyLocation)) { Debug.Assert(false, "Env should create the directory for us"); throw new ProjectUpgradeFailedException(); } // copy project file { var targetFilePath = Path.Combine(copyLocation, projectFileName); if (HasSxSBackupFlag(flag)) { bool ignored; targetFilePath = GetUniqueFileName(targetFilePath + ".old", out ignored); } try { File.Copy(projectFilePath, targetFilePath); logger.LogInfo(SR.GetString(SR.ProjectBackupSuccessful, targetFilePath)); } catch (Exception ex) { var message = SR.GetString(SR.ErrorMakingProjectBackup, targetFilePath); throw new ProjectUpgradeFailedException(string.Format("{0} : {1}", message, ex.Message)); } } if (HasCopyBackupFlag(flag)) { //Now iterate through the project items and copy them to the new location //All projects under the solution retain its folder hierarchy var types = new[] { "Compile", "None", "Content", "EmbeddedResource", "Resource", "BaseApplicationManifest", "ApplicationDefinition", "Page" }; var metadataLookup = convertedProject .Items .GroupBy(i => i.ItemType) .ToDictionary(x => x.Key); var sourceProjectDir = Path.GetDirectoryName(projectFilePath); foreach (var ty in types) { if (metadataLookup.ContainsKey(ty)) { foreach (var item in metadataLookup[ty]) { var linkMetadataElement = item.Metadata.FirstOrDefault(me => me.Name == "Link"); string linked = linkMetadataElement != null && !string.IsNullOrEmpty(linkMetadataElement.Value) ? linkMetadataElement.Value : null; var include = item.Include; Debug.Assert(!string.IsNullOrEmpty(include)); string sourceFilePath; var targetFileName = Path.Combine(copyLocation, linked ?? include); if (Path.IsPathRooted(include)) { //if the path is fully qualified already, then just use it sourceFilePath = include; } else { //otherwise tack the filename on to the path sourceFilePath = Path.Combine(sourceProjectDir, include); } if (linked != null && include[0] == '.') { //if linked file up a level (or more), then turn it into a path without the ..\ in the middle sourceFilePath = Path.GetFullPath(sourceFilePath); } bool initiallyUnique; targetFileName = GetUniqueFileName(targetFileName, out initiallyUnique); if (!initiallyUnique) { logger.LogInfo(SR.GetString(SR.BackupNameConflict, targetFileName)); } //Warn user in upgrade log if linked files are used "project may not build" if (linked != null && HasCopyBackupFlag(flag)) { logger.LogWarning(SR.GetString(SR.ProjectContainsLinkedFile, targetFileName)); } // ensure target folder exists Directory.CreateDirectory(Path.GetDirectoryName(targetFileName)); try { File.Copy(sourceFilePath, targetFileName); logger.LogInfo(SR.GetString(SR.BackupSuccessful, targetFileName)); } catch (Exception ex) { var message = SR.GetString(SR.ErrorMakingBackup, targetFileName); logger.LogError(string.Format("{0} : {1}", message, ex.Message)); } } } } } } }
/// <summary> /// Determines whether a project needs to be upgraded. /// </summary> /// <param name="projectXml"> /// The XML of the project file being upgraded. /// </param> /// <param name="userProjectXml"> /// The XML of the user file being upgraded, or null if no user file /// exists. /// </param> /// <param name="log"> /// Callback to log messages. These messages will be added to the /// migration log that is displayed after upgrading completes. /// </param> /// <param name="projectFactory"> /// The project factory that will be used. This may be replaced with /// another Guid if a new project factory should be used to upgrade the /// project. /// </param> /// <param name="backupSupport"> /// The level of backup support requested for the project. By default, /// the project file (and user file, if any) will be copied alongside /// the originals with ".old" added to the filenames. /// </param> /// <returns> /// The form of upgrade required. /// </returns> protected virtual ProjectUpgradeState UpgradeProjectCheck( ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action<__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport ) { return ProjectUpgradeState.NotNeeded; }
protected override ProjectUpgradeState UpgradeProjectCheck(ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action <__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport) { var envVarsProp = projectXml.Properties.FirstOrDefault(p => p.Name == NodejsConstants.EnvironmentVariables); if (envVarsProp != null && !string.IsNullOrEmpty(envVarsProp.Value)) { return(ProjectUpgradeState.OneWayUpgrade); } return(ProjectUpgradeState.NotNeeded); }
protected override ProjectUpgradeState UpgradeProjectCheck( ProjectRootElement projectXml, ProjectRootElement userProjectXml, Action<__VSUL_ERRORLEVEL, string> log, ref Guid projectFactory, ref __VSPPROJECTUPGRADEVIAFACTORYFLAGS backupSupport ) { Version version; // Referencing an interpreter by GUID if (projectXml.Properties.Where(p => p.Name == "InterpreterId").Any(IsGuidValue) || projectXml.ItemGroups.SelectMany(g => g.Items) .Where(i => i.ItemType == "InterpreterReference") .Any(IsGuidValue) || projectXml.ItemGroups.SelectMany(g => g.Items) .Where(i => i.ItemType == "Interpreter") .SelectMany(i => i.Metadata.Where(m => m.Name == "BaseInterpreter")) .Any(IsGuidValue) ) { return ProjectUpgradeState.OneWayUpgrade; } var imports = new HashSet<string>(projectXml.Imports.Select(p => p.Project), StringComparer.OrdinalIgnoreCase); // Only importing the Common targets and/or props. if (imports.Contains(CommonProps) || imports.Contains(CommonTargets) && imports.Count == 1) { return ProjectUpgradeState.OneWayUpgrade; } // Includes imports from PTVS 2.2 if (projectXml.Properties.Any(IsPtvsTargetsFileProperty)) { return ProjectUpgradeState.SafeRepair; } // Uses web or Django launcher and has no WebBrowserUrl property if (projectXml.Properties.Where(p => p.Name == "LaunchProvider") .Any(p => p.Value == "Web launcher" || p.Value == "Django launcher") && !projectXml.Properties.Any(p => p.Name == "WebBrowserUrl")) { return ProjectUpgradeState.SafeRepair; } // Importing a targets file from 2.1 Beta if (imports.Contains(Ptvs21BetaBottleTargets) || imports.Contains(Ptvs21BetaFlaskTargets)) { return ProjectUpgradeState.SafeRepair; } // ToolsVersion less than 4.0 (or unspecified) is not supported, so // set it to 4.0. if (!Version.TryParse(projectXml.ToolsVersion, out version) || version < new Version(4, 0)) { return ProjectUpgradeState.SafeRepair; } return ProjectUpgradeState.NotNeeded; }