diff options
-rw-r--r-- | tools/build_defs/pkg/BUILD | 22 | ||||
-rw-r--r-- | tools/build_defs/pkg/build_tar.py | 82 | ||||
-rwxr-xr-x | tools/build_defs/pkg/build_test.sh | 16 | ||||
-rw-r--r-- | tools/build_defs/pkg/pkg.bzl | 6 |
4 files changed, 113 insertions, 13 deletions
diff --git a/tools/build_defs/pkg/BUILD b/tools/build_defs/pkg/BUILD index 2f55d7fd0e..cae1a4a03a 100644 --- a/tools/build_defs/pkg/BUILD +++ b/tools/build_defs/pkg/BUILD @@ -174,6 +174,26 @@ pkg_tar( }, ) +pkg_tar( + name = "test-tar-empty_files", + build_tar = ":build_tar", + empty_files = [ + "/a", + "/b", + ], + mode = "0o777", +) + +pkg_tar( + name = "test-tar-empty_dirs", + build_tar = ":build_tar", + empty_dirs = [ + "/tmp", + "/pmt", + ], + mode = "0o777", +) + pkg_deb( name = "test-deb", conffiles = [ @@ -205,6 +225,8 @@ sh_test( ":test-deb.deb", ":test-tar-.tar", ":test-tar-bz2.tar.bz2", + ":test-tar-empty_dirs.tar", + ":test-tar-empty_files.tar", ":test-tar-files_dict.tar", ":test-tar-gz.tar.gz", ":test-tar-inclusion-.tar", diff --git a/tools/build_defs/pkg/build_tar.py b/tools/build_defs/pkg/build_tar.py index a07fd43fb2..e5428041a3 100644 --- a/tools/build_defs/pkg/build_tar.py +++ b/tools/build_defs/pkg/build_tar.py @@ -30,6 +30,10 @@ gflags.DEFINE_multistring('file', [], 'A file to add to the layer') gflags.DEFINE_string( 'mode', None, 'Force the mode on the added files (in octal).') +gflags.DEFINE_multistring('empty_file', [], 'An empty file to add to the layer') + +gflags.DEFINE_multistring('empty_dir', [], 'An empty dir to add to the layer') + gflags.DEFINE_multistring('tar', [], 'A tar file to add to the layer') gflags.DEFINE_multistring('deb', [], 'A debian package to add to the layer') @@ -121,6 +125,56 @@ class TarFile(object): uname=names[0], gname=names[1]) + def add_empty_file(self, + destfile, + mode=None, + ids=None, + names=None, + kind=tarfile.REGTYPE): + """Add a file to the tar file. + + Args: + destfile: the name of the file in the layer + mode: force to set the specified mode, defaults to 644 + ids: (uid, gid) for the file to set ownership + names: (username, groupname) for the file to set ownership. + kind: type of the file. tarfile.DIRTYPE for directory. + + An empty file will be created as `destfile` in the layer. + """ + dest = destfile.lstrip('/') # Remove leading slashes + # If mode is unspecified, assume read only + if mode is None: + mode = 0o644 + if ids is None: + ids = (0, 0) + if names is None: + names = ('', '') + dest = os.path.normpath(dest) + self.tarfile.add_file( + dest, + content='' if kind == tarfile.REGTYPE else None, + kind=kind, + mode=mode, + uid=ids[0], + gid=ids[1], + uname=names[0], + gname=names[1]) + + def add_empty_dir(self, destpath, mode=None, ids=None, names=None): + """Add a directory to the tar file. + + Args: + destpath: the name of the directory in the layer + mode: force to set the specified mode, defaults to 644 + ids: (uid, gid) for the file to set ownership + names: (username, groupname) for the file to set ownership. + + An empty file will be created as `destfile` in the layer. + """ + self.add_empty_file( + destpath, mode=mode, ids=ids, names=names, kind=tarfile.DIRTYPE) + def add_tar(self, tar): """Merge a tar file into the destination tar file. @@ -212,21 +266,23 @@ def main(unused_argv): # Add objects to the tar file with TarFile(FLAGS.output, FLAGS.directory, FLAGS.compression) as output: + + def file_attributes(filename): + if filename[0] == '/': + filename = filename[1:] + return { + 'mode': mode_map.get(filename, default_mode), + 'ids': ids_map.get(filename, default_ids), + 'names': names_map.get(filename, default_ownername), + } + for f in FLAGS.file: (inf, tof) = f.split('=', 1) - mode = default_mode - ids = default_ids - names = default_ownername - map_filename = tof - if tof[0] == '/': - map_filename = tof[1:] - if map_filename in mode_map: - mode = mode_map[map_filename] - if map_filename in ids_map: - ids = ids_map[map_filename] - if map_filename in names_map: - names = names_map[map_filename] - output.add_file(inf, tof, mode, ids, names) + output.add_file(inf, tof, **file_attributes(tof)) + for f in FLAGS.empty_file: + output.add_empty_file(f, **file_attributes(f)) + for f in FLAGS.empty_dir: + output.add_empty_dir(f, **file_attributes(f)) for tar in FLAGS.tar: output.add_tar(tar) for deb in FLAGS.deb: diff --git a/tools/build_defs/pkg/build_test.sh b/tools/build_defs/pkg/build_test.sh index 1322f5006d..99bae8e8fc 100755 --- a/tools/build_defs/pkg/build_test.sh +++ b/tools/build_defs/pkg/build_test.sh @@ -22,9 +22,17 @@ source ${DIR}/testenv.sh || { echo "testenv.sh not found!" >&2; exit 1; } function get_tar_listing() { local input=$1 local test_data="${TEST_DATA_DIR}/${input}" + # We strip unused prefixes rather than dropping "v" flag for tar, because we + # want to preserve symlink information. tar tvf "${test_data}" | sed -e 's/^.*:00 //' } +function get_tar_verbose_listing() { + local input=$1 + local test_data="${TEST_DATA_DIR}/${input}" + TZ="UTC" tar tvf "${test_data}" +} + function get_tar_owner() { local input=$1 local file=$2 @@ -147,6 +155,14 @@ function test_tar() { check_eq "./ ./not-etc/ ./not-etc/mapped-filename.conf" "$(get_tar_listing test-tar-files_dict.tar)" + check_eq "drwxr-xr-x 0/0 0 1970-01-01 00:00 ./ +-rwxrwxrwx 0/0 0 1970-01-01 00:00 ./a +-rwxrwxrwx 0/0 0 1970-01-01 00:00 ./b" \ + "$(get_tar_verbose_listing test-tar-empty_files.tar)" + check_eq "drwxr-xr-x 0/0 0 1970-01-01 00:00 ./ +drwxrwxrwx 0/0 0 1970-01-01 00:00 ./tmp/ +drwxrwxrwx 0/0 0 1970-01-01 00:00 ./pmt/" \ + "$(get_tar_verbose_listing test-tar-empty_dirs.tar)" } function test_deb() { diff --git a/tools/build_defs/pkg/pkg.bzl b/tools/build_defs/pkg/pkg.bzl index b12814dea7..24840eefbd 100644 --- a/tools/build_defs/pkg/pkg.bzl +++ b/tools/build_defs/pkg/pkg.bzl @@ -47,6 +47,10 @@ def _pkg_tar_impl(ctx): if ctx.attr.ownernames: args += ["--owner_names=%s=%s" % (key, ctx.attr.ownernames[key]) for key in ctx.attr.ownernames] + if ctx.attr.empty_files: + args += ["--empty_file=%s" % empty_file for empty_file in ctx.attr.empty_files] + if ctx.attr.empty_dirs: + args += ["--empty_dir=%s" % empty_dir for empty_dir in ctx.attr.empty_dirs] if ctx.attr.extension: dotPos = ctx.attr.extension.find('.') if dotPos > 0: @@ -175,6 +179,8 @@ _real_pkg_tar = rule( "ownernames": attr.string_dict(), "extension": attr.string(default="tar"), "symlinks": attr.string_dict(), + "empty_files": attr.string_list(), + "empty_dirs": attr.string_list(), # Implicit dependencies. "build_tar": attr.label( default=Label("//tools/build_defs/pkg:build_tar"), |