Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set modified timestamps on files being extracted from tar archives #74400

Merged
merged 2 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ private void ExtractAsRegularFile(string destinationFileName)
DataStream?.CopyTo(fs);
}

ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime);
AttemptSetLastWriteTime(destinationFileName, ModificationTime);
}

// Asynchronously extracts the current entry as a regular file into the specified destination.
Expand All @@ -551,7 +551,19 @@ private async Task ExtractAsRegularFileAsync(string destinationFileName, Cancell
}
}

ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, ModificationTime);
AttemptSetLastWriteTime(destinationFileName, ModificationTime);
}

private static void AttemptSetLastWriteTime(string destinationFileName, DateTimeOffset lastWriteTime)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copied from Archiving.Utils.cs where it's also used by Zip as I didn't want to affect Zip in anything we want to port (although, as per discussion in the linked issue, I don't believe it would affect Zip)

{
try
{
File.SetLastWriteTime(destinationFileName, lastWriteTime.LocalDateTime); // SetLastWriteTime expects local time
danmoseley marked this conversation as resolved.
Show resolved Hide resolved
}
catch
{
// Some OSes like Android might not support setting the last write time, the extraction should not fail because of that
}
}

private FileStreamOptions CreateFileStreamOptions(bool isAsync)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public void IncludeAllSegmentsOfPath(bool includeBaseDirectory)
Assert.Null(reader.GetNextEntry());
}

[Fact]
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
public void SkipRecursionIntoDirectorySymlinks()
{
using TempDirectory root = new TempDirectory();
Expand Down Expand Up @@ -225,7 +225,7 @@ public void SkipRecursionIntoDirectorySymlinks()
Assert.Null(reader.GetNextEntry()); // file.txt should not be found
}

[Fact]
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
public void SkipRecursionIntoBaseDirectorySymlink()
{
using TempDirectory root = new TempDirectory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public async Task IncludeAllSegmentsOfPath_Async(bool includeBaseDirectory)
}
}

[Fact]
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
public async Task SkipRecursionIntoDirectorySymlinksAsync()
{
using TempDirectory root = new TempDirectory();
Expand Down Expand Up @@ -269,7 +269,7 @@ public async Task SkipRecursionIntoDirectorySymlinksAsync()
Assert.Null(await reader.GetNextEntryAsync()); // file.txt should not be found
}

[Fact]
[ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))]
danmoseley marked this conversation as resolved.
Show resolved Hide resolved
public async Task SkipRecursionIntoBaseDirectorySymlinkAsync()
{
using TempDirectory root = new TempDirectory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,33 @@ public void NonExistentDirectory_Throws()
Assert.Throws<DirectoryNotFoundException>(() => TarFile.ExtractToDirectory(sourceFileName: filePath, destinationDirectoryName: dirPath, overwriteFiles: false));
}

[Fact]
public void SetsLastModifiedTimeOnExtractedFiles()
{
using TempDirectory root = new TempDirectory();

string inDir = Path.Join(root.Path, "indir");
string inFile = Path.Join(inDir, "file");

string tarFile = Path.Join(root.Path, "file.tar");

string outDir = Path.Join(root.Path, "outdir");
string outFile = Path.Join(outDir, "file");

Directory.CreateDirectory(inDir);
File.Create(inFile).Dispose();
var dt = new DateTime(2001, 1, 2, 3, 4, 5, DateTimeKind.Local);
File.SetLastWriteTime(inFile, dt);

TarFile.CreateFromDirectory(sourceDirectoryName: inDir, destinationFileName: tarFile, includeBaseDirectory: false);

Directory.CreateDirectory(outDir);
TarFile.ExtractToDirectory(sourceFileName: tarFile, destinationDirectoryName: outDir, overwriteFiles: false);

Assert.True(File.Exists(outFile));
Assert.InRange(File.GetLastWriteTime(outFile).Ticks, dt.AddSeconds(-3).Ticks, dt.AddSeconds(3).Ticks); // include some slop for filesystem granularity
}

[Theory]
[InlineData(TestTarFormat.v7)]
[InlineData(TestTarFormat.ustar)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,33 @@ public async Task NonExistentDirectory_Throws_Async()
}
}

[Fact]
public async Task SetsLastModifiedTimeOnExtractedFiles()
{
using TempDirectory root = new TempDirectory();

string inDir = Path.Join(root.Path, "indir");
string inFile = Path.Join(inDir, "file");

string tarFile = Path.Join(root.Path, "file.tar");

string outDir = Path.Join(root.Path, "outdir");
string outFile = Path.Join(outDir, "file");

Directory.CreateDirectory(inDir);
File.Create(inFile).Dispose();
var dt = new DateTime(2001, 1, 2, 3, 4, 5, DateTimeKind.Local);
File.SetLastWriteTime(inFile, dt);

await TarFile.CreateFromDirectoryAsync(sourceDirectoryName: inDir, destinationFileName: tarFile, includeBaseDirectory: false);

Directory.CreateDirectory(outDir);
await TarFile.ExtractToDirectoryAsync(sourceFileName: tarFile, destinationDirectoryName: outDir, overwriteFiles: false);

Assert.True(File.Exists(outFile));
Assert.InRange(File.GetLastWriteTime(outFile).Ticks, dt.AddSeconds(-3).Ticks, dt.AddSeconds(3).Ticks); // include some slop for filesystem granularity
danmoseley marked this conversation as resolved.
Show resolved Hide resolved
}

[Theory]
[InlineData(TestTarFormat.v7)]
[InlineData(TestTarFormat.ustar)]
Expand Down