diff options
5 files changed, 55 insertions, 2 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto index 0fa0b4a15c..472f104ecc 100644 --- a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto +++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto @@ -340,7 +340,8 @@ message File { string name = 1; oneof file { - // A location where the contents of the file can be found. + // A location where the contents of the file can be found. The string is + // encoded according to RFC2396. string uri = 2; // The contents of the file, if they are guaranteed to be short. bytes contents = 3; diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/transports/BuildEventTransportFactory.java b/src/main/java/com/google/devtools/build/lib/buildeventstream/transports/BuildEventTransportFactory.java index a28645dedb..d07f6a59ea 100644 --- a/src/main/java/com/google/devtools/build/lib/buildeventstream/transports/BuildEventTransportFactory.java +++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/transports/BuildEventTransportFactory.java @@ -101,7 +101,7 @@ public enum BuildEventTransportFactory { private static class NullPathConverter implements PathConverter { @Override public String apply(Path path) { - return "file://" + path; + return path.toURI().toString(); } } } diff --git a/src/main/java/com/google/devtools/build/lib/vfs/Path.java b/src/main/java/com/google/devtools/build/lib/vfs/Path.java index a1436b5178..5c3c7bf0e4 100644 --- a/src/main/java/com/google/devtools/build/lib/vfs/Path.java +++ b/src/main/java/com/google/devtools/build/lib/vfs/Path.java @@ -31,6 +31,8 @@ import java.io.Serializable; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Collection; import java.util.IdentityHashMap; import java.util.Objects; @@ -382,6 +384,39 @@ public class Path implements Comparable<Path>, Serializable { } /** + * Returns the path encoded as an {@link URI}. + * + * <p>This concrete implementation returns URIs with "file" as the scheme. + * For Example: + * - On Unix the path "/tmp/foo bar.txt" will be encoded as + * "file:///tmp/foo%20bar.txt". + * - On Windows the path "C:\Temp\Foo Bar.txt" will be encoded as + * "file:///C:/Temp/Foo%20Bar.txt" + * + * <p>Implementors extending this class for special filesystems will likely need to override + * this method. + * + * @throws URISyntaxException if the URI cannot be constructed. + */ + public URI toURI() { + String ps = getPathString(); + if (!ps.startsWith("/")) { + // On Windows URI's need to start with a '/'. i.e. C:\Foo\Bar would be file:///C:/Foo/Bar + ps = "/" + ps; + } + try { + return new URI("file", + // Needs to be "" instead of null, so that toString() will append "//" after the scheme. + // We need this for backwards compatibility reasons as some consumers of the BEP are + // broken. + "", + ps, null, null); + } catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + } + + /** * Returns the path as a string. */ public String getPathString() { diff --git a/src/test/java/com/google/devtools/build/lib/vfs/PathTest.java b/src/test/java/com/google/devtools/build/lib/vfs/PathTest.java index dbdc0186de..8a1e14fbcf 100644 --- a/src/test/java/com/google/devtools/build/lib/vfs/PathTest.java +++ b/src/test/java/com/google/devtools/build/lib/vfs/PathTest.java @@ -26,6 +26,7 @@ import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.ref.WeakReference; +import java.net.URI; import java.util.Collections; import java.util.List; import org.junit.Before; @@ -301,6 +302,13 @@ public class PathTest { assertThat(segment.toString()).isEqualTo("/foo/bar.txt"); } + @Test + public void testToURI() throws Exception { + Path p = root.getRelative("/tmp/foo bar.txt"); + URI uri = p.toURI(); + assertThat(uri.toString()).isEqualTo("file:///tmp/foo%20bar.txt"); + } + private void assertAsFragmentWorks(String expected) { assertThat(filesystem.getPath(expected).asFragment()).isEqualTo(PathFragment.create(expected)); } diff --git a/src/test/java/com/google/devtools/build/lib/windows/PathWindowsTest.java b/src/test/java/com/google/devtools/build/lib/windows/PathWindowsTest.java index e681733c88..1bd3779e66 100644 --- a/src/test/java/com/google/devtools/build/lib/windows/PathWindowsTest.java +++ b/src/test/java/com/google/devtools/build/lib/windows/PathWindowsTest.java @@ -25,6 +25,7 @@ import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.vfs.RootedPath; import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem; import com.google.devtools.build.lib.windows.WindowsFileSystem.WindowsPath; +import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -339,4 +340,12 @@ public class PathWindowsTest { assertThat(actual.getRoot()).isEqualTo(ancestor); assertThat(actual.getRelativePath()).isEqualTo(PathFragment.create("baz")); } + + @Test + public void testToURI() { + // See https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/ + Path p = root.getRelative("Temp\\Foo Bar.txt"); + URI uri = p.toURI(); + assertThat(uri.toString()).isEqualTo("file:///C:/Temp/Foo%20Bar.txt"); + } } |