Skip to content
This repository was archived by the owner on Nov 10, 2023. It is now read-only.

Commit d687248

Browse files
stepanchegfacebook-github-bot
authored andcommitted
Refactor EdenMount to use proper absolute and relative paths
Summary: Instead of just `Path`. To make it clear which paths are which. Reviewed By: xavierd fbshipit-source-id: 18b6c26eafaaea6fb74dbeb3f74a53a0ec9d0433
1 parent 95b90ef commit d687248

8 files changed

Lines changed: 96 additions & 67 deletions

File tree

src/com/facebook/buck/edenfs/EdenMount.java

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.facebook.buck.edenfs;
1818

19+
import com.facebook.buck.core.filesystems.AbsPath;
20+
import com.facebook.buck.core.filesystems.ForwardRelPath;
1921
import com.facebook.buck.util.sha1.Sha1HashCode;
2022
import com.facebook.eden.thrift.EdenError;
2123
import com.facebook.eden.thrift.SHA1Result;
@@ -38,23 +40,23 @@ public class EdenMount {
3840
private final EdenClientResourcePool pool;
3941

4042
/** Value of the mountPoint argument to use when communicating with Eden via the Thrift API. */
41-
private final Path mountPoint;
43+
private final AbsPath mountPoint;
4244

4345
/** Root of the Buck project of interest that is contained by this {@link EdenMount}. */
44-
private final Path projectRoot;
46+
private final AbsPath projectRoot;
4547

4648
/**
4749
* Relative path used to resolve paths under the {@link #projectRoot} in the context of the {@link
4850
* #mountPoint}.
4951
*/
50-
private final Path prefix;
52+
private final ForwardRelPath prefix;
5153

5254
/**
5355
* Creates a new object for communicating with Eden that is bound to the specified (Eden mount
5456
* point, Buck project root) pair. It must be the case that {@code
5557
* projectRoot.startsWith(mountPoint)}.
5658
*/
57-
EdenMount(EdenClientResourcePool pool, Path mountPoint, Path projectRoot) {
59+
EdenMount(EdenClientResourcePool pool, AbsPath mountPoint, AbsPath projectRoot) {
5860
Preconditions.checkArgument(
5961
projectRoot.startsWith(mountPoint),
6062
"Eden mount point %s must contain the Buck project at %s.",
@@ -63,32 +65,32 @@ public class EdenMount {
6365
this.pool = pool;
6466
this.mountPoint = mountPoint;
6567
this.projectRoot = projectRoot;
66-
this.prefix = mountPoint.relativize(projectRoot);
68+
this.prefix = ForwardRelPath.ofRelPath(mountPoint.relativize(projectRoot));
6769
}
6870

6971
/** @return an Eden mount point if {@code projectRoot} is backed by Eden or {@code null}. */
7072
public static Optional<EdenMount> createEdenMountForProjectRoot(
71-
Path projectRoot, EdenClientResourcePool pool) {
72-
Optional<Path> rootPath = EdenUtil.getPathFromEdenConfig(projectRoot, "root");
73+
AbsPath projectRoot, EdenClientResourcePool pool) {
74+
Optional<Path> rootPath = EdenUtil.getPathFromEdenConfig(projectRoot.getPath(), "root");
7375
if (!rootPath.isPresent()) {
7476
return Optional.empty();
7577
}
7678

77-
return Optional.of(new EdenMount(pool, rootPath.get(), projectRoot));
79+
return Optional.of(new EdenMount(pool, AbsPath.of(rootPath.get()), projectRoot));
7880
}
7981

8082
/** @return The root to the Buck project that this {@link EdenMount} represents. */
81-
public Path getProjectRoot() {
83+
public AbsPath getProjectRoot() {
8284
return projectRoot;
8385
}
8486

8587
@VisibleForTesting
86-
Path getPrefix() {
88+
ForwardRelPath getPrefix() {
8789
return prefix;
8890
}
8991

9092
/** @param entry is a path that is relative to {@link #getProjectRoot()}. */
91-
public Sha1HashCode getSha1(Path entry) throws EdenError, IOException, TException {
93+
public Sha1HashCode getSha1(ForwardRelPath entry) throws EdenError, IOException, TException {
9294
try (EdenClientResource client = pool.openClient()) {
9395
List<SHA1Result> results =
9496
client
@@ -109,24 +111,28 @@ public Sha1HashCode getSha1(Path entry) throws EdenError, IOException, TExceptio
109111
* Returns the path relative to {@link #getProjectRoot()} if {@code path} is contained by {@link
110112
* #getProjectRoot()}; otherwise, returns {@link Optional#empty()}.
111113
*/
112-
Optional<Path> getPathRelativeToProjectRoot(Path path) {
114+
Optional<ForwardRelPath> getPathRelativeToProjectRoot(Path path) {
113115
if (path.isAbsolute()) {
114-
if (path.startsWith(projectRoot)) {
115-
return Optional.of(projectRoot.relativize(path));
116+
if (AbsPath.of(path).startsWith(projectRoot)) {
117+
return Optional.of(ForwardRelPath.ofRelPath(projectRoot.relativize(path)));
116118
} else {
117119
return Optional.empty();
118120
}
119121
} else {
120-
return Optional.of(path);
122+
return Optional.of(ForwardRelPath.ofPath(path));
121123
}
122124
}
123125

124126
/**
125127
* @param entry is a path that is relative to {@link #getProjectRoot()}.
126128
* @return a path that is relative to {@link #mountPoint}.
127129
*/
128-
private byte[] normalizePathArg(Path entry) {
129-
return prefix.resolve(entry).toString().getBytes(StandardCharsets.UTF_8);
130+
private byte[] normalizePathArg(ForwardRelPath entry) {
131+
return prefix
132+
.toRelPath(projectRoot.getFileSystem())
133+
.resolve(entry)
134+
.toString()
135+
.getBytes(StandardCharsets.UTF_8);
130136
}
131137

132138
@Override

src/com/facebook/buck/edenfs/EdenProjectFilesystemDelegate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private Optional<Sha1HashCode> computeSha1ViaXAttr(AbsPath path) throws IOExcept
232232

233233
private Optional<Sha1HashCode> computeSha1ViaThrift(
234234
AbsPath path, boolean retryWithRealPathIfEdenError) throws IOException {
235-
Optional<Path> entry = mount.getPathRelativeToProjectRoot(path.getPath());
235+
Optional<ForwardRelPath> entry = mount.getPathRelativeToProjectRoot(path.getPath());
236236
if (entry.isPresent()) {
237237
try {
238238
return Optional.of(mount.getSha1(entry.get()));

src/com/facebook/buck/io/filesystem/impl/DefaultProjectFilesystemFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public DefaultProjectFilesystem createProjectFilesystem(
6767
embeddedCellBuckOutInfo,
6868
buckOutIncludeTargetConfigHash);
6969
ProjectFilesystemDelegatePair delegatePair =
70-
ProjectFilesystemDelegateFactory.newInstance(root.getPath(), config, watchman);
70+
ProjectFilesystemDelegateFactory.newInstance(root, config, watchman);
7171
return new DefaultProjectFilesystem(
7272
root,
7373
extractIgnorePaths(root.getPath(), config, buckPaths, embeddedCellBuckOutInfo),

src/com/facebook/buck/io/filesystem/impl/ProjectFilesystemDelegateFactory.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import com.facebook.buck.io.filesystem.ProjectFilesystemDelegatePair;
2727
import com.facebook.buck.io.watchman.Watchman;
2828
import com.facebook.buck.util.config.Config;
29-
import java.nio.file.Path;
3029
import java.util.Optional;
3130

3231
/**
@@ -46,15 +45,16 @@ private static Optional<Long> getSHA1LoggingThresholdMicroseconds(Config config)
4645

4746
/** Must always create a new delegate for the specified {@code root}. */
4847
public static ProjectFilesystemDelegatePair newInstance(
49-
Path root, Config config, Watchman watchman) {
48+
AbsPath root, Config config, Watchman watchman) {
5049
return new ProjectFilesystemDelegatePair(
5150
getGeneralDelegate(root, config, watchman),
5251
new DefaultProjectFilesystemDelegate(root, getSHA1LoggingThresholdMicroseconds(config)));
5352
}
5453

5554
private static ProjectFilesystemDelegate getGeneralDelegate(
56-
Path root, Config config, Watchman watchman) {
57-
Optional<EdenClientResourcePool> pool = EdenClientResourcePool.tryToCreateEdenClientPool(root);
55+
AbsPath root, Config config, Watchman watchman) {
56+
Optional<EdenClientResourcePool> pool =
57+
EdenClientResourcePool.tryToCreateEdenClientPool(root.getPath());
5858

5959
if (pool.isPresent()) {
6060
Optional<EdenMount> mount = EdenMount.createEdenMountForProjectRoot(root, pool.get());
@@ -66,7 +66,7 @@ private static ProjectFilesystemDelegate getGeneralDelegate(
6666
mount.get().getProjectRoot(), getSHA1LoggingThresholdMicroseconds(config)),
6767
config,
6868
watchman,
69-
AbsPath.of(root));
69+
root);
7070
} else {
7171
LOG.error("Failed to find Eden client for %s.", root);
7272
}

test/com/facebook/buck/edenfs/EdenClientTest.java

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import static org.junit.Assert.assertFalse;
2525
import static org.junit.Assert.assertTrue;
2626

27+
import com.facebook.buck.core.filesystems.AbsPath;
28+
import com.facebook.buck.core.filesystems.ForwardRelPath;
2729
import com.facebook.buck.testutil.PathNormalizer;
2830
import com.facebook.buck.util.environment.Platform;
2931
import com.facebook.eden.thrift.EdenError;
@@ -80,52 +82,59 @@ public void getMountInfosDelegatesToThriftClient() throws EdenError, IOException
8082

8183
@Test
8284
public void getMountForMatchesProjectRootEqualToMount() throws IOException {
83-
Path projectRoot = PathNormalizer.toWindowsPathIfNeeded(fs.getPath("/home/mbolin/src/eden"));
84-
Files.createDirectories(projectRoot);
85+
AbsPath projectRoot =
86+
AbsPath.of(PathNormalizer.toWindowsPathIfNeeded(fs.getPath("/home/mbolin/src/eden")));
87+
Files.createDirectories(projectRoot.getPath());
8588
if (Platform.detect() == Platform.WINDOWS) {
86-
List<String> config = Arrays.asList("[Config]", "root=" + projectRoot.toString());
87-
Files.createDirectories(PathNormalizer.toWindowsPathIfNeeded(projectRoot.resolve(".eden")));
89+
List<String> config = Arrays.asList("[Config]", "root=" + projectRoot);
90+
Files.createDirectories(
91+
PathNormalizer.toWindowsPathIfNeeded(projectRoot.resolve(".eden").getPath()));
8892
Path configFile =
8993
Files.createFile(
90-
PathNormalizer.toWindowsPathIfNeeded(projectRoot.resolve(".eden").resolve("config")));
94+
PathNormalizer.toWindowsPathIfNeeded(
95+
projectRoot.resolve(".eden").resolve("config").getPath()));
9196
Files.write(configFile, config);
9297
} else {
93-
Files.createDirectories(projectRoot.resolve(".eden"));
94-
Files.createSymbolicLink(projectRoot.resolve(".eden").resolve("root"), projectRoot);
98+
Files.createDirectories(projectRoot.resolve(".eden").getPath());
99+
Files.createSymbolicLink(
100+
projectRoot.resolve(".eden").resolve("root").getPath(), projectRoot.getPath());
95101
}
96102

97103
Optional<EdenMount> mount = EdenMount.createEdenMountForProjectRoot(projectRoot, pool);
98104
assertTrue("Should find mount for path.", mount.isPresent());
99105
assertEquals(
100-
PathNormalizer.toWindowsPathIfNeeded(fs.getPath("/home/mbolin/src/eden")),
106+
AbsPath.of(PathNormalizer.toWindowsPathIfNeeded(fs.getPath("/home/mbolin/src/eden"))),
101107
mount.get().getProjectRoot());
102-
assertEquals(fs.getPath(""), mount.get().getPrefix());
108+
assertEquals(ForwardRelPath.EMPTY, mount.get().getPrefix());
103109
}
104110

105111
@Test
106112
public void getMountForMatchesProjectRootUnderMount() throws IOException {
107-
Path edenMountRoot = fs.getPath("/home/mbolin/src/eden");
108-
Path projectRoot = fs.getPath("/home/mbolin/src/eden/deep/project");
109-
Files.createDirectories(projectRoot);
113+
AbsPath edenMountRoot = AbsPath.of(fs.getPath("/home/mbolin/src/eden").toAbsolutePath());
114+
AbsPath projectRoot =
115+
AbsPath.of(fs.getPath("/home/mbolin/src/eden/deep/project").toAbsolutePath());
116+
Files.createDirectories(projectRoot.getPath());
110117
if (Platform.detect() == Platform.WINDOWS) {
111118
List<String> config = Arrays.asList("[Config]", "root=/home/mbolin/src/eden");
112-
Files.createDirectories(edenMountRoot.resolve(".eden"));
113-
Path configFile = Files.createFile(edenMountRoot.resolve(".eden").resolve("config"));
119+
Files.createDirectories(edenMountRoot.resolve(".eden").getPath());
120+
Path configFile =
121+
Files.createFile(edenMountRoot.resolve(".eden").resolve("config").getPath());
114122
Files.write(configFile, config);
115123
} else {
116-
Files.createDirectories(projectRoot.resolve(".eden"));
117-
Files.createSymbolicLink(projectRoot.resolve(".eden").resolve("root"), edenMountRoot);
124+
Files.createDirectories(projectRoot.resolve(".eden").getPath());
125+
Files.createSymbolicLink(
126+
projectRoot.resolve(".eden").resolve("root").getPath(), edenMountRoot.getPath());
118127
}
119128

120129
Optional<EdenMount> mount = EdenMount.createEdenMountForProjectRoot(projectRoot, pool);
121130
assertTrue("Should find mount for path.", mount.isPresent());
122131
assertEquals(projectRoot, mount.get().getProjectRoot());
123-
assertEquals(fs.getPath("deep/project"), mount.get().getPrefix());
132+
assertEquals(ForwardRelPath.of("deep/project"), mount.get().getPrefix());
124133
}
125134

126135
@Test
127136
public void getMountForReturnsNullWhenMissingMountPoint() {
128-
Path projectRoot = Paths.get("/home/mbolin/src/other_project");
137+
AbsPath projectRoot = AbsPath.of(Paths.get("/home/mbolin/src/other_project").toAbsolutePath());
129138
Optional<EdenMount> mount = EdenMount.createEdenMountForProjectRoot(projectRoot, pool);
130139
assertFalse(mount.isPresent());
131140
}

test/com/facebook/buck/edenfs/EdenMountTest.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import static org.junit.Assert.assertEquals;
2424
import static org.junit.Assert.assertTrue;
2525

26+
import com.facebook.buck.core.filesystems.AbsPath;
27+
import com.facebook.buck.core.filesystems.ForwardRelPath;
2628
import com.facebook.buck.testutil.DeepMatcher;
2729
import com.facebook.buck.testutil.PathNormalizer;
2830
import com.facebook.buck.util.environment.Platform;
@@ -52,7 +54,7 @@ public void getSha1DelegatesToThriftClient() throws EdenError, IOException, TExc
5254
EdenClient thriftClient = createMock(EdenClient.class);
5355

5456
FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
55-
Path entry = fs.getPath("LICENSE");
57+
ForwardRelPath entry = ForwardRelPath.of("LICENSE");
5658
HashCode hash = HashCode.fromString("2b8b815229aa8a61e483fb4ba0588b8b6c491890");
5759
SHA1Result sha1Result = new SHA1Result();
5860
sha1Result.setSha1(hash.asBytes());
@@ -67,17 +69,21 @@ public void getSha1DelegatesToThriftClient() throws EdenError, IOException, TExc
6769

6870
EdenClientResourcePool pool =
6971
new EdenClientResourcePool(() -> new TestEdenClientResource(thriftClient));
70-
Path pathToBuck = PathNormalizer.toWindowsPathIfNeeded(fs.getPath("/home/mbolin/src/buck"));
72+
AbsPath pathToBuck =
73+
AbsPath.of(PathNormalizer.toWindowsPathIfNeeded(fs.getPath("/home/mbolin/src/buck")));
7174
if (Platform.detect() == Platform.WINDOWS) {
72-
List<String> config = Arrays.asList("[Config]", "root=" + pathToBuck.toString());
73-
Files.createDirectories(PathNormalizer.toWindowsPathIfNeeded(pathToBuck.resolve(".eden")));
75+
List<String> config = Arrays.asList("[Config]", "root=" + pathToBuck);
76+
Files.createDirectories(
77+
PathNormalizer.toWindowsPathIfNeeded(pathToBuck.resolve(".eden").getPath()));
7478
Path configFile =
7579
Files.createFile(
76-
PathNormalizer.toWindowsPathIfNeeded(pathToBuck.resolve(".eden").resolve("config")));
80+
PathNormalizer.toWindowsPathIfNeeded(
81+
pathToBuck.resolve(".eden").resolve("config").getPath()));
7782
Files.write(configFile, config);
7883
} else {
79-
Files.createDirectories(pathToBuck.resolve(".eden"));
80-
Files.createSymbolicLink(pathToBuck.resolve(".eden").resolve("root"), pathToBuck);
84+
Files.createDirectories(pathToBuck.resolve(".eden").getPath());
85+
Files.createSymbolicLink(
86+
pathToBuck.resolve(".eden").resolve("root").getPath(), pathToBuck.getPath());
8187
}
8288

8389
Optional<EdenMount> mount = EdenMount.createEdenMountForProjectRoot(pathToBuck, pool);
@@ -91,7 +97,7 @@ public void getMountPointReturnsValuePassedToConstructor() {
9197
EdenClient thriftClient = createMock(EdenClient.class);
9298
EdenClientResourcePool pool =
9399
new EdenClientResourcePool(() -> new TestEdenClientResource(thriftClient));
94-
Path mountPoint = Paths.get("/home/mbolin/src/buck");
100+
AbsPath mountPoint = AbsPath.of(Paths.get("/home/mbolin/src/buck").toAbsolutePath());
95101
replay(thriftClient);
96102

97103
EdenMount mount = new EdenMount(pool, mountPoint, mountPoint);
@@ -105,7 +111,7 @@ public void toStringHasExpectedFormatting() {
105111
EdenClient thriftClient = createMock(EdenClient.class);
106112
EdenClientResourcePool pool =
107113
new EdenClientResourcePool(() -> new TestEdenClientResource(thriftClient));
108-
Path mountPoint = Paths.get("/home/mbolin/src/buck");
114+
AbsPath mountPoint = AbsPath.of(Paths.get("/home/mbolin/src/buck").toAbsolutePath());
109115
replay(thriftClient);
110116

111117
EdenMount mount = new EdenMount(pool, mountPoint, mountPoint);

test/com/facebook/buck/edenfs/EdenProjectFilesystemDelegateTest.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import com.facebook.buck.cli.TestWithBuckd;
2929
import com.facebook.buck.core.filesystems.AbsPath;
30+
import com.facebook.buck.core.filesystems.ForwardRelPath;
3031
import com.facebook.buck.event.console.TestEventConsole;
3132
import com.facebook.buck.io.filesystem.ProjectFilesystem;
3233
import com.facebook.buck.io.filesystem.ProjectFilesystemDelegate;
@@ -105,14 +106,15 @@ public void computeSha1ForOrdinaryFileUnderMount() throws IOException, EdenError
105106
new DefaultProjectFilesystemDelegate(root, Optional.empty());
106107

107108
EdenMount mount = createMock(EdenMount.class);
108-
Path path = fs.getPath("foo/bar");
109-
expect(mount.getPathRelativeToProjectRoot(root.resolve(path))).andReturn(Optional.of(path));
109+
ForwardRelPath path = ForwardRelPath.of("foo/bar");
110+
expect(mount.getPathRelativeToProjectRoot(root.resolve(fs.getPath(path.toString()))))
111+
.andReturn(Optional.of(path));
110112
expect(mount.getSha1(path)).andReturn(DUMMY_SHA1);
111113
replay(mount);
112114

113115
EdenProjectFilesystemDelegate edenDelegate =
114116
new EdenProjectFilesystemDelegate(mount, delegate, AbsPath.of(root));
115-
assertEquals(DUMMY_SHA1, edenDelegate.computeSha1(path));
117+
assertEquals(DUMMY_SHA1, edenDelegate.computeSha1(path.toPath(fs)));
116118

117119
verify(mount);
118120
}
@@ -134,10 +136,12 @@ public void computeSha1ForSymlinkUnderMountThatPointsToFileUnderMount()
134136
// Eden will throw when the SHA-1 for the link is requested, but return a SHA-1 when the target
135137
// is requested.
136138
EdenMount mount = createMock(EdenMount.class);
137-
expect(mount.getPathRelativeToProjectRoot(link)).andReturn(Optional.of(fs.getPath("link")));
138-
expect(mount.getPathRelativeToProjectRoot(target)).andReturn(Optional.of(fs.getPath("target")));
139-
expect(mount.getSha1(fs.getPath("link"))).andThrow(new EdenError());
140-
expect(mount.getSha1(fs.getPath("target"))).andReturn(DUMMY_SHA1);
139+
expect(mount.getPathRelativeToProjectRoot(link))
140+
.andReturn(Optional.of(ForwardRelPath.of("link")));
141+
expect(mount.getPathRelativeToProjectRoot(target))
142+
.andReturn(Optional.of(ForwardRelPath.of("target")));
143+
expect(mount.getSha1(ForwardRelPath.of("link"))).andThrow(new EdenError());
144+
expect(mount.getSha1(ForwardRelPath.of("target"))).andReturn(DUMMY_SHA1);
141145
replay(mount);
142146

143147
EdenProjectFilesystemDelegate edenDelegate =
@@ -166,9 +170,10 @@ public void computeSha1ForSymlinkUnderMountThatPointsToFileOutsideMount()
166170
// Eden will throw when the SHA-1 for the link is requested, but return a SHA-1 when the target
167171
// is requested.
168172
EdenMount mount = createMock(EdenMount.class);
169-
expect(mount.getPathRelativeToProjectRoot(link)).andReturn(Optional.of(fs.getPath("link")));
173+
expect(mount.getPathRelativeToProjectRoot(link))
174+
.andReturn(Optional.of(ForwardRelPath.of("link")));
170175
expect(mount.getPathRelativeToProjectRoot(target)).andReturn(Optional.empty());
171-
expect(mount.getSha1(fs.getPath("link"))).andThrow(new EdenError());
176+
expect(mount.getSha1(ForwardRelPath.of("link"))).andThrow(new EdenError());
172177
replay(mount);
173178

174179
EdenProjectFilesystemDelegate edenDelegate =
@@ -346,8 +351,9 @@ public void computeSha1ViaWatchmanFailedWatchmanNotSetup()
346351
"[eden]", "use_watchman_content_sha1 = true", "[eden]", "use_xattr = false");
347352

348353
EdenMount mount = createMock(EdenMount.class);
349-
Path path = fs.getPath("foo/bar");
350-
expect(mount.getPathRelativeToProjectRoot(root.resolve(path))).andReturn(Optional.of(path));
354+
ForwardRelPath path = ForwardRelPath.of("foo/bar");
355+
expect(mount.getPathRelativeToProjectRoot(root.resolve(path.toPath(fs))))
356+
.andReturn(Optional.of(path));
351357
expect(mount.getSha1(path)).andReturn(DUMMY_SHA1);
352358
replay(mount);
353359

@@ -362,7 +368,7 @@ public void computeSha1ViaWatchmanFailedWatchmanNotSetup()
362368
new WatchmanFactory.NullWatchman(
363369
"EdenProjectFilesystemDelegateTest", WatchmanError.TEST),
364370
AbsPath.of(root));
365-
edenDelegate.computeSha1(path);
371+
edenDelegate.computeSha1(path.toPath(fs));
366372
}
367373

368374
@Test

0 commit comments

Comments
 (0)