diff --git a/src/HearThis/Communication/IAndroidLink.cs b/src/HearThis/Communication/IAndroidLink.cs index 320ccd0d..52fd2452 100644 --- a/src/HearThis/Communication/IAndroidLink.cs +++ b/src/HearThis/Communication/IAndroidLink.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using System.Text; - namespace HearThis.Communication { /// diff --git a/src/HearThis/Communication/WindowsLink.cs b/src/HearThis/Communication/WindowsLink.cs index c4130cde..eac8d664 100644 --- a/src/HearThis/Communication/WindowsLink.cs +++ b/src/HearThis/Communication/WindowsLink.cs @@ -59,7 +59,15 @@ public bool TryListFiles(string androidPath, out string list) var sb = new StringBuilder(); foreach (var file in Directory.EnumerateFiles(path, "*.*")) { - sb.Append(Path.GetFileName(file)); + var filename = Path.GetFileName(file); + // REVIEW: When merging this into HT-359, we'll need to consider + // whether/when changes to info.xml files might need to be regarded + // as significant for determining which version to use in merge, since + // it will be more common for the info file to change without any + // clips being modified. + if (filename == "info.xml") + continue; + sb.Append(filename); sb.Append(";"); sb.Append( new FileInfo(file).LastWriteTimeUtc.ToString( diff --git a/src/HearThis/Publishing/ClipRepository.cs b/src/HearThis/Publishing/ClipRepository.cs index 00038267..c748458e 100644 --- a/src/HearThis/Publishing/ClipRepository.cs +++ b/src/HearThis/Publishing/ClipRepository.cs @@ -403,7 +403,7 @@ public static bool ShiftClipsAtOrAfterBlockIfAllClipsAreBeforeDate(string projec Func getRecordingInfo) { var result = ShiftClips(projectName, bookName, chapterNumber1Based, iBlock, 1, - getRecordingInfo, cutoff:cutoff); + getRecordingInfo, cutoff:cutoff, preserveModifiedTime:true); if (result.Error != null) throw result.Error; return result.Attempted == result.SuccessfulMoves; @@ -411,7 +411,7 @@ public static bool ShiftClipsAtOrAfterBlockIfAllClipsAreBeforeDate(string projec private static ClipShiftingResult ShiftClips(string projectName, string bookName, int chapterNumber, int iStartBlock, int offset, Func getRecordingInfo, - int blockCount = MaxValue, DateTime cutoff = default) + int blockCount = MaxValue, DateTime cutoff = default, bool preserveModifiedTime = false) { Debug.Assert(offset != 0); ClipShiftingResult result = null; @@ -451,7 +451,7 @@ private static ClipShiftingResult ShiftClips(string projectName, string bookName result.LastAttemptedMove = null; - getRecordingInfo().AdjustLineNumbers(iStartBlock, offset, blockCount); + getRecordingInfo().AdjustLineNumbers(iStartBlock, offset, blockCount, preserveModifiedTime); } catch (Exception e) { diff --git a/src/HearThis/Script/ChapterInfo.cs b/src/HearThis/Script/ChapterInfo.cs index 6ac4eb49..088b4be0 100644 --- a/src/HearThis/Script/ChapterInfo.cs +++ b/src/HearThis/Script/ChapterInfo.cs @@ -259,13 +259,13 @@ public void RemoveRecordings() Save(); } - protected override void Save() - { - Save(FilePath); - } + protected override void Save(bool preserveModifiedTime = false) => Save(_filePath, preserveModifiedTime); - private void Save(string filePath) + private void Save(string filePath, bool preserveModifiedTime = false) { + var finfo = new FileInfo(filePath); + var modified = finfo.LastWriteTimeUtc; + if (!XmlSerializationHelper.SerializeToFile(filePath, this, out var error)) { Logger.WriteError(error); @@ -275,6 +275,12 @@ private void Save(string filePath) // magically go away. throw new Exception("Unable to save file: " + filePath, error); } + + if (preserveModifiedTime) + { + finfo.LastWriteTimeUtc = modified; + finfo.Attributes |= FileAttributes.Archive; + } } public string ToXmlString() diff --git a/src/HearThis/Script/ChapterRecordingInfoBase.cs b/src/HearThis/Script/ChapterRecordingInfoBase.cs index 054e13dc..c045244b 100644 --- a/src/HearThis/Script/ChapterRecordingInfoBase.cs +++ b/src/HearThis/Script/ChapterRecordingInfoBase.cs @@ -8,7 +8,8 @@ public abstract class ChapterRecordingInfoBase { public abstract IReadOnlyList RecordingInfo { get; } - public void AdjustLineNumbers(int blockNumberOfStartingShiftedClip0Based, int shiftedBy, int blockCount = MaxValue) + public void AdjustLineNumbers(int blockNumberOfStartingShiftedClip0Based, int shiftedBy, int blockCount = MaxValue, + bool preserveModifiedTime = false) { // Note: ScriptLine.Number is 1-based, not 0-based foreach (var recordingInfo in RecordingInfo @@ -18,11 +19,11 @@ public void AdjustLineNumbers(int blockNumberOfStartingShiftedClip0Based, int sh recordingInfo.Number += shiftedBy; } - Save(); + Save(preserveModifiedTime); } public abstract void OnScriptBlockRecorded(ScriptLine selectedScriptBlock); - protected abstract void Save(); + protected abstract void Save(bool preserveModifiedTime = false); } } diff --git a/src/HearThisTests/ClipRepositoryTests.cs b/src/HearThisTests/ClipRepositoryTests.cs index 1a221356..724d7eed 100644 --- a/src/HearThisTests/ClipRepositoryTests.cs +++ b/src/HearThisTests/ClipRepositoryTests.cs @@ -6,7 +6,6 @@ using HearThis.Script; using NUnit.Framework; using SIL.IO; -using static System.Int32; using DateTime = System.DateTime; namespace HearThisTests @@ -1503,13 +1502,14 @@ public void ShiftClipsAtOrAfterBlockIfAllClipsAreBeforeDate_AllFilesModifiedBefo const int kTestChapter = 1; var chapterFolder = ClipRepository.GetChapterFolder(testProject, kTestBook, kTestChapter); - ChapterRecordingInfoBase info; + TestChapterInfo info; if (includeClip0) info = new TestChapterInfo(1, 2, 3, 8); // Intentionally omitted 4, just to make sure the logic is okay with having one missing. else info = new TestChapterInfo(2, 3, 8); // Intentionally omitted 4, just to make sure the logic is okay with having one missing. info.RecordingInfo[1].SkippedChanged += sender => { }; // code requires us to have a handler before we can set it. info.RecordingInfo[1].Skipped = true; + info.ExpectedPreserveModifiedTime = true; try { @@ -1524,6 +1524,7 @@ public void ShiftClipsAtOrAfterBlockIfAllClipsAreBeforeDate_AllFilesModifiedBefo // SUT Assert.IsTrue(ClipRepository.ShiftClipsAtOrAfterBlockIfAllClipsAreBeforeDate( testProject, kTestBook, kTestChapter, 1, DateTime.UtcNow, () => info)); + Assert.AreEqual(includeClip0 ? 5 : 4, Directory.GetFiles(chapterFolder).Length); Assert.That(File.Exists(Path.Combine(chapterFolder, "8.wav"))); Assert.That(File.Exists(Path.Combine(chapterFolder, "4.wav"))); @@ -1531,6 +1532,7 @@ public void ShiftClipsAtOrAfterBlockIfAllClipsAreBeforeDate_AllFilesModifiedBefo Assert.That(File.Exists(Path.Combine(chapterFolder, "2.wav"))); Assert.IsFalse(File.Exists(Path.Combine(chapterFolder, "1.wav"))); Assert.AreEqual(includeClip0, File.Exists(file0)); + Assert.AreEqual(1, info.SaveCallCount); int i = 0; if (includeClip0) @@ -1838,6 +1840,7 @@ private class TestChapterInfo : ChapterRecordingInfoBase private readonly List _recordings; public int SaveCallCount { get; private set; } + public bool ExpectedPreserveModifiedTime { get; set; } public TestChapterInfo(params int[] scriptLineNumbers) { @@ -1852,8 +1855,9 @@ public override void OnScriptBlockRecorded(ScriptLine selectedScriptBlock) throw new NotImplementedException(); } - protected override void Save() + protected override void Save(bool preserveModifiedTime = false) { + Assert.AreEqual(ExpectedPreserveModifiedTime, preserveModifiedTime); SaveCallCount++; } } diff --git a/src/HearThisTests/ScriptProviderBaseTests.cs b/src/HearThisTests/ScriptProviderBaseTests.cs index 48df121e..8167a8cc 100644 --- a/src/HearThisTests/ScriptProviderBaseTests.cs +++ b/src/HearThisTests/ScriptProviderBaseTests.cs @@ -800,8 +800,9 @@ public override void OnScriptBlockRecorded(ScriptLine scriptBlock) _recordings.Add(scriptBlock); } - protected override void Save() + protected override void Save(bool preserveModifiedTime = false) { + Assert.IsTrue(preserveModifiedTime); SaveCallCount++; } }