Skip to content

Commit 54f11fe

Browse files
tjgqcopybara-github
authored andcommitted
Introduce an --incompatible_disallow_symlink_file_to_dir flag so we can eventually disallow calling ctx.actions.symlink on an input directory and an output file.
PiperOrigin-RevId: 466002367 Change-Id: I5a9275deb458ae6388e10c5b941e2ccef2ddaa81
1 parent 3d493dc commit 54f11fe

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkActionFactory.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package com.google.devtools.build.lib.analysis.starlark;
1515

1616
import static com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions.EXPERIMENTAL_SIBLING_REPOSITORY_LAYOUT;
17+
import static com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions.INCOMPATIBLE_DISALLOW_SYMLINK_FILE_TO_DIR;
1718

1819
import com.google.common.base.Joiner;
1920
import com.google.common.collect.ImmutableList;
@@ -282,11 +283,14 @@ public void symlink(
282283
+ "file or directory, not a symlink (did you mean to use declare_file() or "
283284
+ "declare_directory() instead of declare_symlink()?)");
284285
}
285-
// TODO(tjgq): Enforce that input and output are either both files or both directories.
286-
// This requires fixing callers passing a directory as the input and a file as the output.
287-
if (!inputArtifact.isTreeArtifact() && outputArtifact.isTreeArtifact()) {
288-
String inputType = inputArtifact.isTreeArtifact() ? "directory" : "file";
289-
String outputType = outputArtifact.isTreeArtifact() ? "directory" : "file";
286+
287+
boolean inputOutputMismatch =
288+
getSemantics().getBool(INCOMPATIBLE_DISALLOW_SYMLINK_FILE_TO_DIR)
289+
? inputArtifact.isDirectory() != outputArtifact.isDirectory()
290+
: !inputArtifact.isDirectory() && outputArtifact.isDirectory();
291+
if (inputOutputMismatch) {
292+
String inputType = inputArtifact.isDirectory() ? "directory" : "file";
293+
String outputType = outputArtifact.isDirectory() ? "directory" : "file";
290294
throw Starlark.errorf(
291295
"symlink() with \"target_file\" %s param requires that \"output\" be declared as a %s "
292296
+ "(did you mean to use declare_%s() instead of declare_%s()?)",

src/main/java/com/google/devtools/build/lib/packages/semantics/BuildLanguageOptions.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ public final class BuildLanguageOptions extends OptionsBase {
6363

6464
// <== Add new options here in alphabetic order ==>
6565

66+
@Option(
67+
name = "incompatible_disallow_symlink_file_to_dir",
68+
defaultValue = "false",
69+
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
70+
effectTags = {OptionEffectTag.LOADING_AND_ANALYSIS},
71+
metadataTags = {OptionMetadataTag.INCOMPATIBLE_CHANGE},
72+
help =
73+
"If set to true, `ctx.actions.symlink` will disallow symlinking a file into a directory.")
74+
public boolean incompatibleAllowSymlinkFileToDir;
75+
6676
@Option(
6777
name = "experimental_build_setting_api",
6878
defaultValue = "true",
@@ -609,6 +619,7 @@ public StarlarkSemantics toStarlarkSemantics() {
609619
StarlarkSemantics semantics =
610620
StarlarkSemantics.builder()
611621
// <== Add new options here in alphabetic order ==>
622+
.setBool(INCOMPATIBLE_DISALLOW_SYMLINK_FILE_TO_DIR, incompatibleAllowSymlinkFileToDir)
612623
.setBool(EXPERIMENTAL_ALLOW_TAGS_PROPAGATION, experimentalAllowTagsPropagation)
613624
.set(EXPERIMENTAL_BUILTINS_BZL_PATH, experimentalBuiltinsBzlPath)
614625
.setBool(EXPERIMENTAL_BUILTINS_DUMMY, experimentalBuiltinsDummy)
@@ -684,6 +695,8 @@ public StarlarkSemantics toStarlarkSemantics() {
684695
// (In principle, a key not associated with a command-line flag may be declared anywhere.)
685696

686697
// booleans: the +/- prefix indicates the default value (true/false).
698+
public static final String INCOMPATIBLE_DISALLOW_SYMLINK_FILE_TO_DIR =
699+
"-incompatible_disallow_symlink_file_to_dir";
687700
public static final String EXPERIMENTAL_ALLOW_TAGS_PROPAGATION =
688701
"-experimental_allow_tags_propagation";
689702
public static final String EXPERIMENTAL_BUILTINS_DUMMY = "-experimental_builtins_dummy";

src/test/shell/bazel/bazel_symlink_test.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,13 @@ EOF
492492
bazel build //a:a || fail "build failed"
493493
assert_contains "Hello, World!" bazel-bin/a/a.link/inside.txt
494494
expect_symlink bazel-bin/a/a.link
495+
496+
bazel build --noincompatible_disallow_symlink_file_to_dir || fail "build failed"
497+
assert_contains "Hello, World!" bazel-bin/a/a.link/inside.txt
498+
expect_symlink bazel-bin/a/a.link
499+
500+
bazel build --incompatible_disallow_symlink_file_to_dir //a:a >& $TEST_log && fail "build succeeded"
501+
expect_log "symlink() with \"target_file\" directory param requires that \"output\" be declared as a directory"
495502
}
496503

497504
function test_symlink_directory_to_file_created_from_symlink_action() {

0 commit comments

Comments
 (0)