1 | /*- | |
2 | * #%L | |
3 | * io.earcam.instrumental.io.file | |
4 | * %% | |
5 | * Copyright (C) 2018 earcam | |
6 | * %% | |
7 | * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT) | |
8 | * | |
9 | * You <b>must</b> choose to accept, in full - any individual or combination of | |
10 | * the following licenses: | |
11 | * <ul> | |
12 | * <li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li> | |
13 | * <li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li> | |
14 | * <li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li> | |
15 | * <li><a href="https://opensource.org/licenses/MIT">MIT</a></li> | |
16 | * </ul> | |
17 | * #L% | |
18 | */ | |
19 | package io.earcam.utilitarian.io.file; | |
20 | ||
21 | import static java.nio.file.FileVisitOption.FOLLOW_LINKS; | |
22 | import static java.nio.file.FileVisitResult.CONTINUE; | |
23 | import static java.nio.file.LinkOption.NOFOLLOW_LINKS; | |
24 | ||
25 | import java.io.IOException; | |
26 | import java.nio.file.CopyOption; | |
27 | import java.nio.file.FileVisitOption; | |
28 | import java.nio.file.FileVisitResult; | |
29 | import java.nio.file.Files; | |
30 | import java.nio.file.LinkOption; | |
31 | import java.nio.file.Path; | |
32 | import java.nio.file.SimpleFileVisitor; | |
33 | import java.nio.file.attribute.BasicFileAttributes; | |
34 | import java.util.Arrays; | |
35 | import java.util.EnumSet; | |
36 | ||
37 | /** | |
38 | * Wise to invoke these methods with {@link LinkOption#NOFOLLOW_LINKS} | |
39 | */ | |
40 | public final class RecursiveFiles { | |
41 | ||
42 | private abstract static class AbstractVisitor extends SimpleFileVisitor<Path> { | |
43 | ||
44 | final Path sink; | |
45 | final Path source; | |
46 | final CopyOption[] options; | |
47 | ||
48 | Path sinkSub; | |
49 | ||
50 | ||
51 | public AbstractVisitor(Path source, Path sink, CopyOption... options) | |
52 | { | |
53 | this.source = source; | |
54 | this.sink = sink; | |
55 | this.options = options; | |
56 | } | |
57 | ||
58 | ||
59 | @Override | |
60 | public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException | |
61 | { | |
62 | sinkSub = sink.resolve(source.relativize(dir)); | |
63 | sinkSub.toFile().mkdirs(); | |
64 |
1
1. preVisitDirectory : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$AbstractVisitor::preVisitDirectory to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CONTINUE; |
65 | } | |
66 | ||
67 | ||
68 | @Override | |
69 | public FileVisitResult postVisitDirectory(Path directory, IOException thrown) throws IOException | |
70 | { | |
71 | super.postVisitDirectory(directory, thrown); | |
72 |
1
1. postVisitDirectory : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$AbstractVisitor::postVisitDirectory to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return postVisitDirectory(directory); |
73 | } | |
74 | ||
75 | ||
76 | protected abstract FileVisitResult postVisitDirectory(Path directory) throws IOException; | |
77 | ||
78 | ||
79 | @Override | |
80 | public abstract FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException; | |
81 | } | |
82 | ||
83 | private static final class DeleteVisitor extends AbstractVisitor { | |
84 | ||
85 | public DeleteVisitor(Path source, CopyOption... options) | |
86 | { | |
87 | super(source, source, options); | |
88 | } | |
89 | ||
90 | ||
91 | @Override | |
92 | public FileVisitResult postVisitDirectory(Path directory) throws IOException | |
93 | { | |
94 |
1
1. postVisitDirectory : removed call to java/nio/file/Files::delete → KILLED |
Files.delete(directory); |
95 |
1
1. postVisitDirectory : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$DeleteVisitor::postVisitDirectory to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CONTINUE; |
96 | } | |
97 | ||
98 | ||
99 | @Override | |
100 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException | |
101 | { | |
102 |
1
1. visitFile : removed call to java/nio/file/Files::delete → KILLED |
Files.delete(file); |
103 |
1
1. visitFile : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$DeleteVisitor::visitFile to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CONTINUE; |
104 | } | |
105 | } | |
106 | ||
107 | private static final class MoveVisitor extends AbstractVisitor { | |
108 | ||
109 | public MoveVisitor(Path source, Path sink, CopyOption... options) | |
110 | { | |
111 | super(source, sink, options); | |
112 | } | |
113 | ||
114 | ||
115 | @Override | |
116 | protected FileVisitResult postVisitDirectory(Path directory) throws IOException | |
117 | { | |
118 |
1
1. postVisitDirectory : removed call to java/nio/file/Files::delete → KILLED |
Files.delete(directory); |
119 |
1
1. postVisitDirectory : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$MoveVisitor::postVisitDirectory to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CONTINUE; |
120 | } | |
121 | ||
122 | ||
123 | @Override | |
124 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException | |
125 | { | |
126 | Files.move(file, sinkSub.resolve(file.getFileName()), options); | |
127 |
1
1. visitFile : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$MoveVisitor::visitFile to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CONTINUE; |
128 | } | |
129 | } | |
130 | ||
131 | private static final class CopyVisitor extends AbstractVisitor { | |
132 | ||
133 | public CopyVisitor(Path source, Path sink, CopyOption... options) | |
134 | { | |
135 | super(source, sink, options); | |
136 | } | |
137 | ||
138 | ||
139 | @Override | |
140 | protected FileVisitResult postVisitDirectory(Path directory) | |
141 | { | |
142 |
1
1. postVisitDirectory : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$CopyVisitor::postVisitDirectory to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CONTINUE; |
143 | } | |
144 | ||
145 | ||
146 | @Override | |
147 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException | |
148 | { | |
149 | Files.copy(file, sinkSub.resolve(file.getFileName()), options); | |
150 |
1
1. visitFile : mutated return of Object value for io/earcam/utilitarian/io/file/RecursiveFiles$CopyVisitor::visitFile to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CONTINUE; |
151 | } | |
152 | } | |
153 | ||
154 | ||
155 | private RecursiveFiles() | |
156 | {} | |
157 | ||
158 | ||
159 | /** | |
160 | * Wise to invoke this with {@link LinkOption#NOFOLLOW_LINKS} | |
161 | * | |
162 | * @param path | |
163 | * @param options | |
164 | * @throws IOException | |
165 | */ | |
166 | public static void delete(Path path, LinkOption... options) throws IOException | |
167 | { | |
168 |
1
1. delete : removed call to io/earcam/utilitarian/io/file/RecursiveFiles::recurse → KILLED |
recurse(path, new DeleteVisitor(path, options)); |
169 | } | |
170 | ||
171 | ||
172 | /** | |
173 | * Wise to invoke this with {@link LinkOption#NOFOLLOW_LINKS} | |
174 | * | |
175 | * @param source | |
176 | * @param sink | |
177 | * @param options | |
178 | * @throws IOException | |
179 | */ | |
180 | public static void move(Path source, Path sink, CopyOption... options) throws IOException | |
181 | { | |
182 |
1
1. move : removed call to io/earcam/utilitarian/io/file/RecursiveFiles::recurse → KILLED |
recurse(source, new MoveVisitor(source, sink, options)); |
183 | } | |
184 | ||
185 | ||
186 | private static void recurse(Path source, AbstractVisitor visitor) throws IOException | |
187 | { | |
188 | boolean noFollow = Arrays.asList(visitor.options).contains(NOFOLLOW_LINKS); | |
189 |
1
1. recurse : negated conditional → KILLED |
EnumSet<FileVisitOption> options = noFollow ? EnumSet.noneOf(FileVisitOption.class) : EnumSet.of(FOLLOW_LINKS); |
190 | ||
191 | Files.walkFileTree(source, options, Integer.MAX_VALUE, visitor); | |
192 | } | |
193 | ||
194 | ||
195 | /** | |
196 | * Wise to invoke this with {@link LinkOption#NOFOLLOW_LINKS} | |
197 | * | |
198 | * @param source | |
199 | * @param sink | |
200 | * @param options | |
201 | * @throws IOException | |
202 | */ | |
203 | public static void copy(Path source, Path sink, CopyOption... options) throws IOException | |
204 | { | |
205 |
1
1. copy : removed call to io/earcam/utilitarian/io/file/RecursiveFiles::recurse → KILLED |
recurse(source, new CopyVisitor(source, sink, options)); |
206 | } | |
207 | } | |
Mutations | ||
64 |
1.1 |
|
72 |
1.1 |
|
94 |
1.1 |
|
95 |
1.1 |
|
102 |
1.1 |
|
103 |
1.1 |
|
118 |
1.1 |
|
119 |
1.1 |
|
127 |
1.1 |
|
142 |
1.1 |
|
150 |
1.1 |
|
168 |
1.1 |
|
182 |
1.1 |
|
189 |
1.1 |
|
205 |
1.1 |