public bool UpdateExternalLinks(string sOldLinkedFilesRootDir)
{
ILangProject lp = Cache.LanguageProject;
string sNewLinkedFilesRootDir = lp.LinkedFilesRootDir;
if (!FileUtils.PathsAreEqual(sNewLinkedFilesRootDir, sOldLinkedFilesRootDir))
{
List<string> rgFilesToMove = new List<string>();
// TODO: offer to move or copy existing files.
foreach (ICmFolder cf in lp.MediaOC)
CollectMovableFilesFromFolder(cf, rgFilesToMove, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir);
foreach (ICmFolder cf in lp.PicturesOC)
CollectMovableFilesFromFolder(cf, rgFilesToMove, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir);
//Get the files which are pointed to by links in TsStrings
CollectMovableFilesFromFolder(lp.FilePathsInTsStringsOA, rgFilesToMove, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir);
var hyperlinks = StringServices.GetHyperlinksInFolder(Cache, sOldLinkedFilesRootDir);
foreach (var linkInfo in hyperlinks)
{
if (!rgFilesToMove.Contains(linkInfo.RelativePath) &&
FileUtils.SimilarFileExists(Path.Combine(sOldLinkedFilesRootDir, linkInfo.RelativePath)) &&
!FileUtils.SimilarFileExists(Path.Combine(sNewLinkedFilesRootDir, linkInfo.RelativePath)))
{
rgFilesToMove.Add(linkInfo.RelativePath);
}
}
if (rgFilesToMove.Count > 0)
{
FileLocationChoice action;
using (MoveOrCopyFilesDlg dlg = new MoveOrCopyFilesDlg()) // REVIEW (Hasso) 2015.08: should this go in MoveOrCopyFilesController?
{
dlg.Initialize(rgFilesToMove.Count, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir, this);
DialogResult res = dlg.ShowDialog();
Debug.Assert(res == DialogResult.OK);
if (res != DialogResult.OK)
return false; // should never happen!
action = dlg.Choice;
}
if (action == FileLocationChoice.Leave) // Expand path
{
NonUndoableUnitOfWorkHelper.Do(Cache.ActionHandlerAccessor,
() =>
{
foreach (ICmFolder cf in lp.MediaOC)
ExpandToFullPath(cf, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir);
foreach (ICmFolder cf in lp.PicturesOC)
ExpandToFullPath(cf, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir);
});
// Hyperlinks are always already full paths.
return false;
}
List<string> rgLockedFiles = new List<string>();
foreach (string sFile in rgFilesToMove)
{
string sOldPathname = Path.Combine(sOldLinkedFilesRootDir, sFile);
string sNewPathname = Path.Combine(sNewLinkedFilesRootDir, sFile);
string sNewDir = Path.GetDirectoryName(sNewPathname);
if (!Directory.Exists(sNewDir))
Directory.CreateDirectory(sNewDir);
Debug.Assert(FileUtils.TrySimilarFileExists(sOldPathname, out sOldPathname));
if (FileUtils.TrySimilarFileExists(sNewPathname, out sNewPathname))
File.Delete(sNewPathname);
try
{
if (action == FileLocationChoice.Move)
{
//LT-13343 do copy followed by delete to ensure the file gets put in the new location.
//If the current FLEX record has a picture displayed the File.Delete will fail.
File.Copy(sOldPathname, sNewPathname);
File.Delete(sOldPathname);
}
else
File.Copy(sOldPathname, sNewPathname);
}
catch (Exception ex)
{
Debug.WriteLine(String.Format("{0}: {1}", ex.Message, sOldPathname));
rgLockedFiles.Add(sFile);
}
}
NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(Cache.ActionHandlerAccessor,
() => StringServices.FixHyperlinkFolder(hyperlinks, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir));
// If any files failed to be moved or copied above, try again now that we've
// opened a new window and had more time elapse (and more demand to reuse
// memory) since the failure.
if (rgLockedFiles.Count > 0)
{
GC.Collect(); // make sure the window is disposed!
Thread.Sleep(1000);
foreach (string sFile in rgLockedFiles)
{
string sOldPathname = Path.Combine(sOldLinkedFilesRootDir, sFile);
string sNewPathname = Path.Combine(sNewLinkedFilesRootDir, sFile);
try
{
if (action == FileLocationChoice.Move)
FileUtils.Move(sOldPathname, sNewPathname);
else
File.Copy(sOldPathname, sNewPathname);
}
catch (Exception ex)
{
Debug.WriteLine(String.Format("{0}: {1} (SECOND ATTEMPT)", ex.Message, sOldPathname));
}
}
}
return true;
}
}
return false;
}