Skip to content

Commit b663e0c

Browse files
c-mitacopybara-github
authored andcommitted
Add and use an "ignore" option to FilesetEntry.symlinks, treating them like regular files.
Internal change for Fileset "simplification". PiperOrigin-RevId: 671425783 Change-Id: I648dc799de3b041a1c04f41f8279d2333328d8f1
1 parent 1ad5e18 commit b663e0c

File tree

5 files changed

+56
-51
lines changed

5 files changed

+56
-51
lines changed

src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParams.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.devtools.build.lib.vfs.PathFragment;
2525
import com.google.devtools.build.lib.vfs.Root;
2626
import com.google.devtools.build.lib.vfs.RootedPath;
27+
import java.util.Locale;
2728
import java.util.Objects;
2829
import javax.annotation.Nullable;
2930

@@ -36,6 +37,27 @@
3637
*/
3738
public interface FilesetTraversalParams {
3839

40+
/** Specifies how symlinks should be treated. */
41+
enum SymlinkBehavior {
42+
/** Symlinks are treated as regular files (the same as the runfiles output tree). */
43+
IGNORE,
44+
45+
/** Symlinks are copied to the output tree. */
46+
COPY,
47+
48+
/** Symlinks are dereferenced and the underlying file is used for the output tree. */
49+
DEREFERENCE;
50+
51+
public static SymlinkBehavior parse(String value) throws IllegalArgumentException {
52+
return valueOf(value.toUpperCase(Locale.ROOT));
53+
}
54+
55+
@Override
56+
public String toString() {
57+
return super.toString().toLowerCase(Locale.ROOT);
58+
}
59+
}
60+
3961
/** Desired behavior if the traversal hits a directory with a BUILD file, i.e. a subpackage. */
4062
enum PackageBoundaryMode {
4163
/** The traversal should recurse into the directory, optionally reporting a warning. */
@@ -173,8 +195,8 @@ abstract class DirectTraversal {
173195
/** Returns true if the root points to a generated file, symlink or directory. */
174196
public abstract boolean isGenerated();
175197

176-
/** Returns true if input symlinks should be dereferenced; false if copied. */
177-
public abstract boolean isFollowingSymlinks();
198+
/** Returns the desired behaviour for handling symlinks */
199+
public abstract SymlinkBehavior getSymlinkBehavior();
178200

179201
/** Returns the desired behavior when the traversal hits a subpackage. */
180202
public abstract PackageBoundaryMode getPackageBoundaryMode();
@@ -193,25 +215,25 @@ abstract class DirectTraversal {
193215
byte[] getFingerprint() {
194216
Fingerprint fp = new Fingerprint();
195217
fp.addPath(getRoot().asPath());
196-
fp.addBoolean(isFollowingSymlinks());
197218
fp.addBoolean(isGenerated());
198219
fp.addBoolean(isStrictFilesetOutput());
199220
fp.addBoolean(permitDirectories());
200221
getPackageBoundaryMode().fingerprint(fp);
222+
fp.addInt(getSymlinkBehavior().ordinal());
201223
return fp.digestAndReset();
202224
}
203225

204226
static DirectTraversal getDirectTraversal(
205227
DirectTraversalRoot root,
206-
boolean followingSymlinks,
228+
SymlinkBehavior symlinkBehavior,
207229
PackageBoundaryMode packageBoundaryMode,
208230
boolean isStrictFilesetOutput,
209231
boolean permitSourceDirectories,
210232
boolean isGenerated) {
211233
return new AutoValue_FilesetTraversalParams_DirectTraversal(
212234
root,
213235
isGenerated,
214-
followingSymlinks,
236+
symlinkBehavior,
215237
packageBoundaryMode,
216238
isStrictFilesetOutput,
217239
permitSourceDirectories);

src/main/java/com/google/devtools/build/lib/actions/FilesetTraversalParamsFactory.java

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,15 @@
1919
import com.google.common.collect.Ordering;
2020
import com.google.devtools.build.lib.actions.FilesetTraversalParams.DirectTraversalRoot;
2121
import com.google.devtools.build.lib.actions.FilesetTraversalParams.PackageBoundaryMode;
22+
import com.google.devtools.build.lib.actions.FilesetTraversalParams.SymlinkBehavior;
2223
import com.google.devtools.build.lib.cmdline.Label;
23-
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
24-
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
2524
import com.google.devtools.build.lib.util.Fingerprint;
2625
import com.google.devtools.build.lib.vfs.PathFragment;
27-
import java.util.Locale;
2826
import java.util.Set;
2927
import javax.annotation.Nullable;
3028

3129
/** Factory of {@link FilesetTraversalParams}. */
3230
public final class FilesetTraversalParamsFactory {
33-
/** SymlinkBehavior decides what to do when a source file of a FilesetEntry is a symlink. */
34-
@Immutable
35-
@ThreadSafe
36-
public enum SymlinkBehavior {
37-
/** Just copies the symlink as-is. May result in dangling links. */
38-
COPY,
39-
/** Follow the link and make the destination point to the absolute path of the final target. */
40-
DEREFERENCE;
41-
42-
public static SymlinkBehavior parse(String value) throws IllegalArgumentException {
43-
return valueOf(value.toUpperCase(Locale.ENGLISH));
44-
}
45-
46-
@Override
47-
public String toString() {
48-
return super.toString().toLowerCase();
49-
}
50-
}
5131

5232
/**
5333
* Creates parameters for a file traversal request.
@@ -149,7 +129,7 @@ static DirectoryTraversalParams getDirectoryTraversalParams(
149129
DirectTraversal traversal =
150130
DirectTraversal.getDirectTraversal(
151131
root,
152-
symlinkBehaviorMode == SymlinkBehavior.DEREFERENCE,
132+
symlinkBehaviorMode,
153133
pkgBoundaryMode,
154134
strictFilesetOutput,
155135
permitDirectories,

src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,17 @@ public SkyValue compute(SkyKey key, Environment env)
179179

180180
PathFragment targetName;
181181
try {
182-
targetName = f.getTargetInSymlinkTree(direct.isFollowingSymlinks());
182+
switch (direct.getSymlinkBehavior()) {
183+
case COPY:
184+
targetName = f.getTargetInSymlinkTree(false);
185+
break;
186+
case DEREFERENCE:
187+
targetName = f.getTargetInSymlinkTree(true);
188+
break;
189+
default:
190+
targetName = f.getPath().asPath().asFragment();
191+
break;
192+
}
183193
} catch (DanglingSymlinkException e) {
184194
throw new FilesetEntryFunctionException(e);
185195
}

src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ public FileType getType() {
404404
@Override
405405
@Nullable
406406
public RootedPath getPath() {
407-
return null;
407+
return symlink.linkName;
408408
}
409409

410410
@Override
@@ -473,7 +473,7 @@ public FileType getType() {
473473

474474
@Override
475475
public RootedPath getPath() {
476-
return path;
476+
return symlink.linkName;
477477
}
478478

479479
@Override
@@ -537,7 +537,7 @@ public FileType getType() {
537537

538538
@Override
539539
public RootedPath getPath() {
540-
return path;
540+
return symlink.linkName;
541541
}
542542

543543
@Override
@@ -622,12 +622,7 @@ public interface ResolvedFile {
622622
/** Type of the entity under {@link #getPath()}. */
623623
FileType getType();
624624

625-
/**
626-
* Path of the file, directory or resolved target of the symlink.
627-
*
628-
* <p>May only return null for dangling symlinks.
629-
*/
630-
@Nullable
625+
/** Path of the file, directory or symlink. */
631626
RootedPath getPath();
632627

633628
/**
@@ -644,6 +639,7 @@ public interface ResolvedFile {
644639
* should have necessary prefixes stripped (if any).
645640
*/
646641
PathFragment getNameInSymlinkTree();
642+
647643

648644
/**
649645
* Returns the path of the symlink target.

src/test/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunctionTest.java

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
3131
import com.google.devtools.build.lib.actions.FilesetTraversalParams;
3232
import com.google.devtools.build.lib.actions.FilesetTraversalParams.PackageBoundaryMode;
33+
import com.google.devtools.build.lib.actions.FilesetTraversalParams.SymlinkBehavior;
3334
import com.google.devtools.build.lib.actions.FilesetTraversalParamsFactory;
34-
import com.google.devtools.build.lib.actions.FilesetTraversalParamsFactory.SymlinkBehavior;
3535
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
3636
import com.google.devtools.build.lib.analysis.BlazeDirectories;
3737
import com.google.devtools.build.lib.analysis.ServerDirectories;
@@ -237,7 +237,7 @@ public void testFileTraversalForFile() throws Exception {
237237
/* ownerLabel= */ label("//foo"),
238238
/* fileToTraverse= */ file,
239239
PathFragment.create("output-name"),
240-
/* symlinkBehaviorMode= */ FilesetTraversalParamsFactory.SymlinkBehavior.COPY,
240+
/* symlinkBehaviorMode= */ SymlinkBehavior.COPY,
241241
/* pkgBoundaryMode= */ DONT_CROSS,
242242
/* strictFilesetOutput= */ false,
243243
/* permitDirectories= */ false);
@@ -272,12 +272,12 @@ private void assertFileTraversalForFileSymlink(SymlinkBehavior symlinks) throws
272272

273273
@Test
274274
public void testFileTraversalForFileSymlinkNoFollow() throws Exception {
275-
assertFileTraversalForFileSymlink(FilesetTraversalParamsFactory.SymlinkBehavior.COPY);
275+
assertFileTraversalForFileSymlink(SymlinkBehavior.COPY);
276276
}
277277

278278
@Test
279279
public void testFileTraversalForFileSymlinkFollow() throws Exception {
280-
assertFileTraversalForFileSymlink(FilesetTraversalParamsFactory.SymlinkBehavior.DEREFERENCE);
280+
assertFileTraversalForFileSymlink(SymlinkBehavior.DEREFERENCE);
281281
}
282282

283283
@Test
@@ -291,7 +291,7 @@ public void testFileTraversalForDirectory() throws Exception {
291291
/* ownerLabel= */ label("//foo"),
292292
/* fileToTraverse= */ dir,
293293
PathFragment.create("output-name"),
294-
/* symlinkBehaviorMode= */ FilesetTraversalParamsFactory.SymlinkBehavior.COPY,
294+
/* symlinkBehaviorMode= */ SymlinkBehavior.COPY,
295295
/* pkgBoundaryMode= */ DONT_CROSS,
296296
/* strictFilesetOutput= */ false,
297297
/* permitDirectories= */ true);
@@ -310,7 +310,7 @@ public void testFileTraversalForDisallowedDirectoryThrows() throws Exception {
310310
/* ownerLabel= */ label("//foo"),
311311
/* fileToTraverse= */ dir,
312312
PathFragment.create("output-name"),
313-
/* symlinkBehaviorMode= */ FilesetTraversalParamsFactory.SymlinkBehavior.COPY,
313+
/* symlinkBehaviorMode= */ SymlinkBehavior.COPY,
314314
/* pkgBoundaryMode= */ DONT_CROSS,
315315
/* strictFilesetOutput= */ false,
316316
/* permitDirectories= */ false);
@@ -353,13 +353,12 @@ private void assertFileTraversalForDirectorySymlink(SymlinkBehavior symlinks) th
353353

354354
@Test
355355
public void testFileTraversalForDirectorySymlinkFollow() throws Exception {
356-
assertFileTraversalForDirectorySymlink(FilesetTraversalParamsFactory.SymlinkBehavior.COPY);
356+
assertFileTraversalForDirectorySymlink(SymlinkBehavior.COPY);
357357
}
358358

359359
@Test
360360
public void testFileTraversalForDirectorySymlinkNoFollow() throws Exception {
361-
assertFileTraversalForDirectorySymlink(
362-
FilesetTraversalParamsFactory.SymlinkBehavior.DEREFERENCE);
361+
assertFileTraversalForDirectorySymlink(SymlinkBehavior.DEREFERENCE);
363362
}
364363

365364
@Test
@@ -374,7 +373,7 @@ public void testFileTraversalForDanglingSymlink() throws Exception {
374373
/* ownerLabel= */ label("//foo"),
375374
/* fileToTraverse= */ linkName,
376375
PathFragment.create("output-name"),
377-
/* symlinkBehaviorMode= */ FilesetTraversalParamsFactory.SymlinkBehavior.COPY,
376+
/* symlinkBehaviorMode= */ SymlinkBehavior.COPY,
378377
/* pkgBoundaryMode= */ DONT_CROSS,
379378
/* strictFilesetOutput= */ false,
380379
/* permitDirectories= */ false);
@@ -389,7 +388,7 @@ public void testFileTraversalForNonExistentFile() throws Exception {
389388
/* ownerLabel= */ label("//foo"),
390389
/* fileToTraverse= */ path,
391390
PathFragment.create("output-name"),
392-
/* symlinkBehaviorMode= */ FilesetTraversalParamsFactory.SymlinkBehavior.COPY,
391+
/* symlinkBehaviorMode= */ SymlinkBehavior.COPY,
393392
/* pkgBoundaryMode= */ DONT_CROSS,
394393
/* strictFilesetOutput= */ false,
395394
/* permitDirectories= */ false);
@@ -494,9 +493,7 @@ public void testFingerprintOfFileTraversal() throws Exception {
494493
.put("destPath", partOfFingerprint("out1", "out2"))
495494
.put(
496495
"symlinkBehaviorMode",
497-
partOfFingerprint(
498-
FilesetTraversalParamsFactory.SymlinkBehavior.COPY,
499-
FilesetTraversalParamsFactory.SymlinkBehavior.DEREFERENCE))
496+
partOfFingerprint(SymlinkBehavior.COPY, SymlinkBehavior.DEREFERENCE))
500497
.put("pkgBoundaryMode", partOfFingerprint(CROSS, DONT_CROSS))
501498
.put("strictFilesetOutput", partOfFingerprint(true, false))
502499
.put("permitDirectories", partOfFingerprint(true, false))

0 commit comments

Comments
 (0)