in vsintegration/src/FSharp.ProjectSystem.Base/Project/ProjectFactory.cs [580:697]
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));
}
}
}
}
}
}
}