Skip to content

Commit 6d0af2c

Browse files
ronodnnrnascimento
andauthored
📦 Conditionally preserve file mtime when archiving through pkg_tar (#974)
* preserve file mtime through an option * add tests * delete debug comment * wrap long line * buildifier --------- Co-authored-by: rnascimento <[email protected]>
1 parent 9c05cf6 commit 6d0af2c

File tree

4 files changed

+50
-4
lines changed

4 files changed

+50
-4
lines changed

‎pkg/private/tar/build_tar.py‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class DebError(Exception):
4444
pass
4545

4646
def __init__(self, output, directory, compression, compressor, create_parents,
47-
allow_dups_from_deps, default_mtime, compression_level, preserve_mode):
47+
allow_dups_from_deps, default_mtime, compression_level, preserve_mode,
48+
preserve_mtime):
4849
# Directory prefix on all output paths
4950
d = directory.strip('/')
5051
self.directory = (d + '/') if d else None
@@ -56,6 +57,7 @@ def __init__(self, output, directory, compression, compressor, create_parents,
5657
self.allow_dups_from_deps = allow_dups_from_deps
5758
self.compression_level = compression_level
5859
self.preserve_mode = preserve_mode
60+
self.preserve_mtime = preserve_mtime
5961

6062
def __enter__(self):
6163
self.tarfile = tar_writer.TarFileWriter(
@@ -90,7 +92,7 @@ def normalize_path(self, path: str) -> str:
9092
dest = self.directory + dest
9193
return dest
9294

93-
def add_file(self, f, destfile, mode=None, ids=None, names=None):
95+
def add_file(self, f, destfile, mode=None, ids=None, names=None, mtime=None):
9496
"""Add a file to the tar file.
9597
9698
Args:
@@ -110,6 +112,8 @@ def add_file(self, f, destfile, mode=None, ids=None, names=None):
110112
mode = stat.S_IMODE(os.stat(f).st_mode)
111113
elif mode is None:
112114
mode = 0o755 if os.access(f, os.X_OK) else 0o644
115+
if self.preserve_mtime is True:
116+
mtime = os.stat(f).st_mtime
113117
if ids is None:
114118
ids = (0, 0)
115119
if names is None:
@@ -121,7 +125,8 @@ def add_file(self, f, destfile, mode=None, ids=None, names=None):
121125
uid=ids[0],
122126
gid=ids[1],
123127
uname=names[0],
124-
gname=names[1])
128+
gname=names[1],
129+
mtime=mtime)
125130

126131
def add_empty_file(self,
127132
destfile,
@@ -412,6 +417,10 @@ def main():
412417
'--preserve_mode', default='False',
413418
action='store_true',
414419
help='Preserve original file permissions in the archive. Mode argument is ignored.')
420+
parser.add_argument(
421+
'--preserve_mtime', default='False',
422+
action='store_true',
423+
help='Preserve original file mtime in the archive. mtime argument is ignored.')
415424
parser.add_argument(
416425
'--compression_level', default=-1,
417426
help='Specify the numeric compress level in gzip mode; may be 0-9 or -1 (default to 6).')
@@ -472,7 +481,8 @@ def main():
472481
create_parents=options.create_parents,
473482
allow_dups_from_deps=options.allow_dups_from_deps,
474483
compression_level = compression_level,
475-
preserve_mode = options.preserve_mode) as output:
484+
preserve_mode = options.preserve_mode,
485+
preserve_mtime = options.preserve_mtime) as output:
476486

477487
def file_attributes(filename):
478488
if filename.startswith('/'):

‎pkg/private/tar/tar.bzl‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ def _pkg_tar_impl(ctx):
184184
if ctx.attr.preserve_mode:
185185
args.add("--preserve_mode")
186186

187+
if ctx.attr.preserve_mtime:
188+
args.add("--preserve_mtime")
189+
187190
inputs = depset(
188191
direct = ctx.files.deps + files,
189192
transitive = mapping_context.file_deps,
@@ -301,6 +304,10 @@ builds were accidentally doing it. Never explicitly set this to true for new cod
301304
default = False,
302305
doc = """If true, will add file to archive with preserved file permissions.""",
303306
),
307+
"preserve_mtime": attr.bool(
308+
default = False,
309+
doc = """If true, will add file to archive with preserved file mtime.""",
310+
),
304311
"stamp": attr.int(
305312
doc = """Enable file time stamping. Possible values:
306313
<li>stamp = 1: Use the time of the build as the modification time of each file in the archive.

‎tests/tar/BUILD‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ py_test(
476476
":test-tar-mtime.tar",
477477
":test-tar-preserve_mode-False.tar",
478478
":test-tar-preserve_mode-True.tar",
479+
":test-tar-preserve_mtime-False.tar",
480+
":test-tar-preserve_mtime-True.tar",
479481
":test-tar-repackaging-long-filename.tar",
480482
":test-tar-strip_prefix-dot.tar",
481483
":test-tar-strip_prefix-empty.tar",
@@ -814,3 +816,14 @@ verify_archive_test(
814816
True,
815817
False,
816818
]]
819+
820+
[pkg_tar(
821+
name = "test-tar-preserve_mtime-%s" % state,
822+
srcs = [
823+
"//tests:testdata/hello.txt",
824+
],
825+
preserve_mtime = state,
826+
) for state in [
827+
True,
828+
False,
829+
]]

‎tests/tar/pkg_tar_test.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,5 +324,21 @@ def test_preserve_mode(self):
324324
self.assertEqual(member.name, "hello.txt", "unexpected file name for " + file_name)
325325
self.assertEqual(member.mode, int(expected_mode, 0), 'file mode not preserved for ' + file_name)
326326

327+
def test_preserve_mtime(self):
328+
test_cases = [
329+
# tar file name, mtime should be equal to PORTABLE_MTIME?
330+
('test-tar-preserve_mtime-False.tar', True),
331+
('test-tar-preserve_mtime-True.tar', False),
332+
]
333+
for file_name, should_be_equal_to_portable_mtime in test_cases:
334+
file_path = runfiles.Create().Rlocation('rules_pkg/tests/tar/' + file_name)
335+
with tarfile.open(file_path, 'r') as f:
336+
for member in f.getmembers():
337+
self.assertEqual(member.name, "hello.txt", "unexpected file name for " + file_name)
338+
if should_be_equal_to_portable_mtime:
339+
self.assertEqual(member.mtime, PORTABLE_MTIME, "unexpected mtime for " + file_name)
340+
else:
341+
self.assertNotEqual(member.mtime, PORTABLE_MTIME, "file mtime not preserved for " + file_name)
342+
327343
if __name__ == '__main__':
328344
unittest.main()

0 commit comments

Comments
 (0)