in vsintegration/src/FSharp.ProjectSystem.Base/Project/ProjectFactory.cs [415:578]
public virtual int UpgradeProject(
string projectFilePath,
uint upgradeFlag,
string initialCopyLocation,
out string upgradeFullyQualifiedFileName,
IVsUpgradeLogger upgradeLogger,
out int upgradeRequired,
out Guid newProjectFactory
)
{
// initialize out params in case of failure
upgradeFullyQualifiedFileName = null;
upgradeRequired = 0;
newProjectFactory = Guid.Empty;
__VSPPROJECTUPGRADEVIAFACTORYFLAGS flag;
string copyLocation = initialCopyLocation;
var r = NormalizeUpgradeFlag(upgradeFlag, out flag, ref copyLocation);
if (r != VSConstants.S_OK)
{
return r;
}
string projectName = Path.GetFileNameWithoutExtension(projectFilePath);
var logger = new ProjectUpgradeLogger(upgradeLogger, projectName, projectFilePath);
uint ignore;
((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly(projectFilePath, upgradeLogger, out upgradeRequired, out newProjectFactory, out ignore);
// no upgrade required and not 'copy-backup'
if (upgradeRequired == 0 && !HasCopyBackupFlag(flag))
{
//Write an informational message "No upgrade required for project foo"?
logger.LogInfo(SR.GetString(SR.ProjectConversionNotRequired));
logger.LogInfo(SR.GetString(SR.ConversionNotRequired));
upgradeFullyQualifiedFileName = projectFilePath;
return VSConstants.S_OK;
}
// upgrade is not required but backup may still be needed
var projectFileName = Path.GetFileName(projectFilePath);
upgradeFullyQualifiedFileName = projectFilePath;
if (HasSxSBackupFlag(flag))
{
// for SxS call use location near the original file
copyLocation = Path.GetDirectoryName(projectFilePath);
}
// workflow is taken from vsprjfactory.cpp (vsproject\vsproject)
// 1. convert the project (in-memory)
// 2. save SCC related info
// 3. use data stored on step 2 in GetSccInfo calls (during QueryEditFiles)
// 4. if succeeded - save project on disk
// F# doesn't use .user file so all related code is skipped
try
{
// load MSBuild project in memory: this will be needed in all cases not depending whether upgrade is required or not
// we use this project to determine the set of files to copy
ProjectRootElement convertedProject = ConvertProject(projectFilePath, logger);
if (convertedProject == null)
{
throw new ProjectUpgradeFailedException();
}
// OK, we need upgrade, save SCC info and ask if project file can be edited
if (upgradeRequired != 0)
{
// 2. save SCC related info
this.m_lastUpgradedProjectFile = projectFilePath;
foreach (var property in convertedProject.Properties)
{
switch (property.Name)
{
case SCC_LOCAL_PATH:
this.m_sccLocalPath = property.Value;
break;
case SCC_AUX_PATH:
this.m_sccAuxPath = property.Value;
break;
case SCC_PROVIDER:
this.m_sccProvider = property.Value;
break;
case SCC_PROJECT_NAME:
this.m_sccProjectName = property.Value;
break;
default:
break;
}
}
// 3. Query for edit (this call may query information stored on previous step)
IVsQueryEditQuerySave2 queryEdit = site.GetService(typeof(SVsQueryEditQuerySave)) as IVsQueryEditQuerySave2;
if (queryEdit != null)
{
uint editVerdict;
uint queryEditMoreInfo;
const tagVSQueryEditFlags tagVSQueryEditFlags_QEF_AllowUnopenedProjects = (tagVSQueryEditFlags)0x80;
int hr = queryEdit.QueryEditFiles(
(uint)(tagVSQueryEditFlags.QEF_ForceEdit_NoPrompting | tagVSQueryEditFlags.QEF_DisallowInMemoryEdits | tagVSQueryEditFlags_QEF_AllowUnopenedProjects),
1, new[] { projectFilePath }, null, null, out editVerdict, out queryEditMoreInfo);
if (ErrorHandler.Failed(hr))
{
throw new ProjectUpgradeFailedException();
}
if (editVerdict != (uint)tagVSQueryEditResult.QER_EditOK)
{
throw new ProjectUpgradeFailedException(SR.GetString(SR.UpgradeCannotOpenProjectFileForEdit));
}
// If file was modified during the checkout, maybe upgrade is not needed
if ((queryEditMoreInfo & (uint)tagVSQueryEditResultFlags.QER_MaybeChanged) != 0)
{
((IVsProjectUpgradeViaFactory)this).UpgradeProject_CheckOnly(projectFilePath, upgradeLogger, out upgradeRequired, out newProjectFactory, out ignore);
if (upgradeRequired == 0)
{
if (logger != null)
{
logger.LogInfo(SR.GetString(SR.UpgradeNoNeedToUpgradeAfterCheckout));
}
return VSConstants.S_OK;
}
}
}
}
// 3.1 copy backup
BackupProjectFilesIfNeeded(projectFilePath, logger, flag, copyLocation, convertedProject);
// 4. if we have performed upgrade - save project to disk
if (upgradeRequired != 0)
{
try
{
convertedProject.Save(projectFilePath);
}
catch (Exception ex)
{
throw new ProjectUpgradeFailedException(ex.Message, ex);
}
}
// 821083: "Converted" should NOT be localized - it is referenced in the XSLT used to display the UpgradeReport
logger.LogStatus("Converted");
}
catch (ProjectUpgradeFailedException ex)
{
var exception = ex.InnerException ?? ex;
if (exception != null && !string.IsNullOrEmpty(exception.Message))
logger.LogError(exception.Message);
upgradeFullyQualifiedFileName = "";
m_lastUpgradedProjectFile = null;
return VSConstants.E_FAIL;
}
return VSConstants.S_OK;
}