Revert "Revert "dist: forbid multiple inputs which create same file""
This reverts commit aa00391e1120bb04b359b4717905ee31ad198f14.
Reason for revert: Relanding change
Change-Id: Ia1e34944cc20c868d29aa0cf71bf857863f60a6f
diff --git a/dist/dist.bzl b/dist/dist.bzl
index 23b6596..bab387e 100644
--- a/dist/dist.bzl
+++ b/dist/dist.bzl
@@ -66,6 +66,7 @@
archive_prefix = None,
dist_dir = None,
wipe_dist_dir = None,
+ allow_duplicate_filenames = None,
log = None,
**kwargs):
"""A dist rule to copy files out of Bazel's output directory into a custom location.
@@ -103,6 +104,14 @@
See details by running the target with `--help`.
wipe_dist_dir: If true, and `dist_dir` already exists, `dist_dir` will be removed prior to
copying.
+ allow_duplicate_filenames: If true, duplicate filenames from different sources will be allowed to
+ be copied to the same `dist_dir` (with subsequent sources overwriting previous sources).
+
+ With this option enabled, order matters. The final source of the file listed in `data` will be the
+ final version copied.
+
+ Use of this option is discouraged. Preferably, the input `data` targets would not include labels
+ which produce a duplicate filename. This option is available as a last resort.
log: If specified, `--log <log>` is provided to the script by default. This sets the
default log level of the script.
@@ -128,6 +137,8 @@
default_args += ["--dist_dir", dist_dir]
if wipe_dist_dir:
default_args.append("--wipe_dist_dir")
+ if allow_duplicate_filenames:
+ default_args.append("--allow_duplicate_filenames")
if log != None:
default_args += ["--log", log]
diff --git a/dist/dist.py b/dist/dist.py
index 580b686..c384664 100644
--- a/dist/dist.py
+++ b/dist/dist.py
@@ -32,6 +32,7 @@
"""
import argparse
+import collections
import glob
import logging
import os
@@ -39,6 +40,21 @@
import sys
import tarfile
+def ensure_unique_filenames(files):
+ basename_to_srcs_map = collections.defaultdict(list)
+ for f in files:
+ basename_to_srcs_map[os.path.basename(f)].append(f)
+
+ duplicates_exist = False
+ for (basename, srcs) in basename_to_srcs_map.items():
+ if len(srcs) > 1:
+ duplicates_exist = True
+ logging.error('Destination filename "%s" has multiple possible sources: %s',
+ basename, srcs)
+
+ if duplicates_exist:
+ sys.exit(1)
+
def files_to_dist(pattern):
# Assume that dist.bzl is in the same package as dist.py
@@ -56,7 +72,10 @@
def copy_files_to_dist_dir(files, archives, dist_dir, flat, prefix,
- strip_components, archive_prefix, wipe_dist_dir, **ignored):
+ strip_components, archive_prefix, wipe_dist_dir, allow_duplicate_filenames, **ignored):
+
+ if flat and not allow_duplicate_filenames:
+ ensure_unique_filenames(files)
if wipe_dist_dir and os.path.exists(dist_dir):
shutil.rmtree(dist_dir)
@@ -139,6 +158,11 @@
action="store_true",
help="remove existing dist_dir prior to running"
)
+ parser.add_argument(
+ "--allow_duplicate_filenames",
+ action="store_true",
+ help="allow multiple files with the same name to be copied to dist_dir (overwriting)"
+ )
args = parser.parse_args(sys.argv[1:])