From 7b17632caa177e92ecd3234fe505e0f8b4cc5f45 Mon Sep 17 00:00:00 2001 From: ascopes <73482956+ascopes@users.noreply.github.com> Date: Sun, 21 Apr 2024 12:23:53 +0100 Subject: [PATCH] Make Shlex emit line continutations --- .../protobufmavenplugin/utils/Shlex.java | 55 ++++++++++++++----- .../protobufmavenplugin/utils/ShlexTest.java | 22 +++++++- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/protobuf-maven-plugin/src/main/java/io/github/ascopes/protobufmavenplugin/utils/Shlex.java b/protobuf-maven-plugin/src/main/java/io/github/ascopes/protobufmavenplugin/utils/Shlex.java index a0125c70..a5d520c7 100644 --- a/protobuf-maven-plugin/src/main/java/io/github/ascopes/protobufmavenplugin/utils/Shlex.java +++ b/protobuf-maven-plugin/src/main/java/io/github/ascopes/protobufmavenplugin/utils/Shlex.java @@ -16,7 +16,7 @@ package io.github.ascopes.protobufmavenplugin.utils; -import java.util.function.BiConsumer; +import java.util.function.Function; /** * Shell/batch file quoting. @@ -24,25 +24,35 @@ *

Losely based on Python's {@code shlex} module. * *

This is far from perfect but should work in the majority of use cases - * to ensure scripts do not interpret special characters in paths in strange and unexpected ways. + * to ensure scripts do not interpret special characters in paths in strange + * and unexpected ways. + * + *

Long lines will be split up with line continuations. * * @author Ashley Scopes */ public final class Shlex { + private static final int LINE_LENGTH_TARGET = 99; + private static final String INDENT = " ".repeat(4); + private Shlex() { // Static-only class } public static String quoteShellArgs(Iterable args) { - return quote(args, Shlex::quoteShellArg); + return quote(args, Shlex::quoteShellArg, " \\\n"); } public static String quoteBatchArgs(Iterable args) { - return quote(args, Shlex::quoteBatchArg); + return quote(args, Shlex::quoteBatchArg, " ^\r\n"); } - private static String quote(Iterable args, BiConsumer quoter) { + private static String quote( + Iterable args, + Function quoter, + String continuation + ) { var iter = args.iterator(); if (!iter.hasNext()) { @@ -50,23 +60,34 @@ private static String quote(Iterable args, BiConsumer= LINE_LENGTH_TARGET) { + sb.append(continuation); + lineLength = INDENT.length(); + sb.append(INDENT); + } else { + sb.append(" "); + lineLength += 1; + } + + sb.append(next); + lineLength += next.length(); } return sb.toString(); } - private static void quoteShellArg(StringBuilder sb, String arg) { + private static String quoteShellArg(String arg) { if (isSafe(arg)) { - sb.append(arg); - return; + return arg; } + var sb = new StringBuilder(); sb.append('\''); for (var i = 0; i < arg.length(); ++i) { var c = arg.charAt(i); @@ -89,14 +110,16 @@ private static void quoteShellArg(StringBuilder sb, String arg) { } } sb.append('\''); + + return sb.toString(); } - private static void quoteBatchArg(StringBuilder sb, String arg) { + private static String quoteBatchArg(String arg) { if (isSafe(arg)) { - sb.append(arg); - return; + return arg; } + var sb = new StringBuilder(); for (var i = 0; i < arg.length(); ++i) { var c = arg.charAt(i); switch (c) { @@ -121,6 +144,8 @@ private static void quoteBatchArg(StringBuilder sb, String arg) { break; } } + + return sb.toString(); } private static boolean isSafe(String arg) { diff --git a/protobuf-maven-plugin/src/test/java/io/github/ascopes/protobufmavenplugin/utils/ShlexTest.java b/protobuf-maven-plugin/src/test/java/io/github/ascopes/protobufmavenplugin/utils/ShlexTest.java index 33e47db6..567cde68 100644 --- a/protobuf-maven-plugin/src/test/java/io/github/ascopes/protobufmavenplugin/utils/ShlexTest.java +++ b/protobuf-maven-plugin/src/test/java/io/github/ascopes/protobufmavenplugin/utils/ShlexTest.java @@ -85,7 +85,16 @@ static Stream quoteShellArgsTestCases() { arguments(list("'potato'"), "''\"'\"'potato'\"'\"''"), arguments(list("foo\nbar", "baz"), "'foo'$'\\n''bar' baz"), arguments(list("foo\rbar", "baz"), "'foo'$'\\r''bar' baz"), - arguments(list("foo\tbar", "baz"), "'foo'$'\\t''bar' baz") + arguments(list("foo\tbar", "baz"), "'foo'$'\\t''bar' baz"), + arguments( + list("a".repeat(100), "b".repeat(100), "c".repeat(100)), + String.join( + " \\\n ", + "a".repeat(100), + "b".repeat(100), + "c".repeat(100) + ) + ) ); } @@ -115,7 +124,16 @@ static Stream quoteBatchArgsTestCases() { arguments(list("<"), "^<"), arguments(list(">"), "^>"), arguments(list("|"), "^|"), - arguments(list("100% complete", "0% incomplete"), "100%%^ complete 0%%^ incomplete") + arguments(list("100% complete", "0% incomplete"), "100%%^ complete 0%%^ incomplete"), + arguments( + list("a".repeat(100), "b".repeat(100), "c".repeat(100)), + String.join( + " ^\r\n ", + "a".repeat(100), + "b".repeat(100), + "c".repeat(100) + ) + ) ); }