Skip to content

Commit 0872bf7

Browse files
committed
New feature: sorting of .proto files
The order in which .proto files are given to the compiler is file system dependent, and thus by extension also operating system dependent, which doesn't matter much for code generation, but can be critical for documentation generation (for which protoc plugins exist!). This commit adds an optional parameter "sortProtoFiles" which can be set to true (defaults to false) to have the .proto files be sorted lexicographically according to their path and file names.
1 parent 34f9ae4 commit 0872bf7

File tree

1 file changed

+59
-5
lines changed

1 file changed

+59
-5
lines changed

src/main/java/dev/cookiecode/maven/plugin/protobuf/AbstractProtocMojo.java

+59-5
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,13 @@
4848

4949
import java.io.File;
5050
import java.io.IOException;
51+
import java.nio.file.Path;
5152
import java.security.MessageDigest;
5253
import java.security.NoSuchAlgorithmException;
53-
import java.util.ArrayList;
54-
import java.util.Enumeration;
55-
import java.util.List;
56-
import java.util.Set;
54+
import java.util.*;
5755
import java.util.jar.JarEntry;
5856
import java.util.jar.JarFile;
57+
import java.util.stream.Collectors;
5958

6059
import static java.lang.Math.max;
6160
import static java.lang.String.format;
@@ -392,6 +391,22 @@ abstract class AbstractProtocMojo extends AbstractMojo {
392391
)
393392
private boolean clearOutputDirectory;
394393

394+
/**
395+
* When {@code true}, the .proto files to be compiled will be sorted before providing their
396+
* paths to the protoc compiler. Otherwise, the order depends on the order in which the
397+
* files are returned from the file system, which is nondeterministic and differs between
398+
* file systems (and thus between Windows and macOS/Linux, for example).
399+
* <p>
400+
* This can for example be relevant when using documentation generation plugins for protoc.
401+
*
402+
* @since 0.7.2
403+
*/
404+
@Parameter(
405+
required = false,
406+
defaultValue = "false"
407+
)
408+
private boolean sortProtoFiles;
409+
395410
/**
396411
* Executes the mojo.
397412
*/
@@ -886,7 +901,11 @@ protected List<File> findProtoFilesInDirectory(final File directory) {
886901
} catch (IOException e) {
887902
throw new MojoInitializationException("Unable to retrieve the list of files: " + e.getMessage(), e);
888903
}
889-
return protoFilesInDirectory;
904+
if(sortProtoFiles) {
905+
return sortProtoFiles(protoFilesInDirectory);
906+
} else {
907+
return protoFilesInDirectory;
908+
}
890909
}
891910

892911
protected List<File> findProtoFilesInDirectories(final Iterable<File> directories) {
@@ -900,6 +919,41 @@ protected List<File> findProtoFilesInDirectories(final Iterable<File> directorie
900919
return protoFiles;
901920
}
902921

922+
/**
923+
* Sorts the given list of .proto files lexicographically.
924+
* <p>
925+
* This results in an order like
926+
* <ol>
927+
* <li>/top1/a.proto</li>
928+
* <li>/top1/sub1/a.proto</li>
929+
* <li>/top1/sub1/b.proto</li>
930+
* <li>/top1/sub1/bot1/d.proto</li>
931+
* <li>/top1/sub1/bot2/c.proto</li>
932+
* <li>/top1/sub2/x.proto</li>
933+
* <li>/top2/z.proto</li>
934+
* <li>/top2/sub1/y.proto</li>
935+
* </ol>
936+
*
937+
* @param unsortedFiles the unsorted list of files
938+
* @return the sorted list
939+
*/
940+
protected List<File> sortProtoFiles(final List<File> unsortedFiles) {
941+
return unsortedFiles.stream().sorted((aFirst, aSecond) -> {
942+
final Path first = aFirst.getAbsoluteFile().toPath();
943+
final Path firstParent = first.getParent();
944+
final Path second = aSecond.getAbsoluteFile().toPath();
945+
final Path secondParent = second.getParent();
946+
947+
// In case of equal parent directories, compare the file names
948+
if(firstParent.equals(secondParent)) {
949+
return first.getFileName().compareTo(second.getFileName());
950+
} else {
951+
// For different parent directories, sort parents lexicographically
952+
return firstParent.compareTo(secondParent);
953+
}
954+
}).collect(Collectors.toList());
955+
}
956+
903957
/**
904958
* Truncates the path of jar files so that they are relative to the local repository.
905959
*

0 commit comments

Comments
 (0)