Skip to content

Commit 7bd761f

Browse files
authored
Merge pull request #1 from SpecialThing44/add-file-argument
Add file argument
2 parents 94a2649 + f3c200a commit 7bd761f

File tree

7 files changed

+108
-15
lines changed

7 files changed

+108
-15
lines changed

geequel-shell/src/main/java/org/neo4j/shell/Main.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void startShell(@Nonnull CliArgs cliArgs) {
106106
try {
107107
CypherShell shell = new CypherShell(logger, prettyConfig);
108108
// Can only prompt for password if input has not been redirected
109-
connectMaybeInteractively(shell, connectionConfig, isInputInteractive(), isOutputInteractive());
109+
connectMaybeInteractively(shell, connectionConfig, isInputInteractive(cliArgs), isOutputInteractive());
110110

111111
// Construct shell runner after connecting, due to interrupt handling
112112
ShellRunner shellRunner = ShellRunner.getShellRunner(cliArgs, shell, logger, connectionConfig);

geequel-shell/src/main/java/org/neo4j/shell/ShellRunner.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@
3131
import org.neo4j.shell.parser.ShellStatementParser;
3232

3333
import javax.annotation.Nonnull;
34-
import java.io.File;
35-
import java.io.FileOutputStream;
36-
import java.io.IOException;
37-
import java.io.OutputStream;
34+
import java.io.*;
3835
import java.nio.charset.Charset;
36+
import java.nio.file.Files;
37+
import java.nio.file.Paths;
3938

4039
import static org.fusesource.jansi.internal.CLibrary.STDIN_FILENO;
4140
import static org.fusesource.jansi.internal.CLibrary.STDOUT_FILENO;
@@ -80,8 +79,9 @@ static ShellRunner getShellRunner(@Nonnull CliArgs cliArgs,
8079
return new InteractiveShellRunner(cypherShell, cypherShell, logger, new ShellStatementParser(),
8180
System.in, FileHistorian.getDefaultHistoryFile(), userMessagesHandler);
8281
} else {
82+
InputStream inputStream = cliArgs.getFile().isPresent() ? Files.newInputStream(Paths.get(cliArgs.getFile().get())) : System.in;
8383
return new NonInteractiveShellRunner(cliArgs.getFailBehavior(), cypherShell, logger,
84-
new ShellStatementParser(), System.in);
84+
new ShellStatementParser(), inputStream);
8585
}
8686
}
8787

@@ -94,7 +94,7 @@ static boolean shouldBeInteractive(@Nonnull CliArgs cliArgs) {
9494
return false;
9595
}
9696

97-
return isInputInteractive();
97+
return isInputInteractive(cliArgs);
9898
}
9999

100100
/**
@@ -104,18 +104,18 @@ static boolean shouldBeInteractive(@Nonnull CliArgs cliArgs) {
104104
* @return true if the shell is reading from an interactive terminal, false otherwise (e.g., we are reading from a
105105
* file).
106106
*/
107-
static boolean isInputInteractive() {
107+
static boolean isInputInteractive(@Nonnull CliArgs cliArgs) {
108108
if (isWindows()) {
109109
// Input will never be a TTY on windows and it isatty seems to be able to block forever on Windows so avoid
110110
// calling it.
111-
return System.console() != null;
111+
return System.console() != null && !cliArgs.getFile().isPresent();
112112
}
113113
try {
114114
return 1 == isatty(STDIN_FILENO);
115115
} catch (Throwable ignored) {
116116
// system is not using libc (like Alpine Linux)
117117
// Fallback to checking stdin OR stdout
118-
return System.console() != null;
118+
return System.console() != null && !cliArgs.getFile().isPresent();
119119
}
120120
}
121121

geequel-shell/src/main/java/org/neo4j/shell/cli/CliArgHelper.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ public static CliArgs parse(@Nonnull String... args) {
9191
// Other arguments
9292
// geequel string might not be given, represented by null
9393
cliArgs.setCypher(ns.getString("geequel"));
94-
// Fail behavior as sensible default and returns a proper type
95-
cliArgs.setFailBehavior(ns.get("fail-behavior"));
94+
95+
cliArgs.setFile(ns.getString("file"));
9696

9797
//Set Output format
98-
cliArgs.setFormat(Format.parse(ns.get("format")));
98+
cliArgs.setFormat(Format.parse(ns.get("format"), cliArgs));
9999

100100
cliArgs.setEncryption(ns.getBoolean("encryption"));
101101

@@ -111,6 +111,9 @@ public static CliArgs parse(@Nonnull String... args) {
111111

112112
cliArgs.setDriverVersion(ns.getBoolean("driver-version"));
113113

114+
// Fail behavior as sensible default and returns a proper type
115+
cliArgs.setFailBehavior(ns.get("fail-behavior"));
116+
114117
return cliArgs;
115118
}
116119

@@ -181,6 +184,10 @@ private static ArgumentParser setupParser()
181184
.help("print additional debug information")
182185
.action(new StoreTrueArgumentAction());
183186

187+
parser.addArgument("-f", "--file")
188+
.help("specify a file to run as a cypher script")
189+
.setDefault("");
190+
184191
parser.addArgument("--non-interactive")
185192
.help("force non-interactive mode, only useful if auto-detection fails (like on Windows)")
186193
.dest("force-non-interactive")

geequel-shell/src/main/java/org/neo4j/shell/cli/CliArgs.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class CliArgs {
4444
private boolean driverVersion = false;
4545
private int numSampleRows = DEFAULT_NUM_SAMPLE_ROWS;
4646
private boolean wrap = true;
47+
private Optional<String> file = Optional.empty();
4748

4849
/**
4950
* Set the scheme to the primary value, or if null, the fallback value.
@@ -101,6 +102,13 @@ public void setCypher(@Nullable String cypher) {
101102
this.cypher = Optional.ofNullable(cypher);
102103
}
103104

105+
/**
106+
* Set the file path to the cypher script to execute
107+
*/
108+
public void setFile (@Nullable String file) {
109+
this.file = Optional.ofNullable(file);
110+
}
111+
104112
/**
105113
* Set whether the connection should be encrypted
106114
*/
@@ -156,6 +164,11 @@ public Optional<String> getCypher() {
156164
return cypher;
157165
}
158166

167+
@Nonnull
168+
public Optional<String> getFile() {
169+
return file;
170+
}
171+
159172
@Nonnull
160173
public Format getFormat() {
161174
return format;

geequel-shell/src/main/java/org/neo4j/shell/cli/Format.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ public enum Format {
3333
PLAIN;
3434
// TODO JSON, strictly intended for machine consumption with data formatted in JSON
3535

36-
public static Format parse(@Nonnull String format) {
36+
public static Format parse(@Nonnull String format, @Nonnull CliArgs cliArgs) {
3737
if (format.equalsIgnoreCase(PLAIN.name())) {
3838
return PLAIN;
3939
} else if (format.equalsIgnoreCase( VERBOSE.name() )) {
4040
return VERBOSE;
4141
} else {
42-
return isInputInteractive() && isOutputInteractive() ? VERBOSE : PLAIN;
42+
return isInputInteractive(cliArgs) && isOutputInteractive() ? VERBOSE : PLAIN;
4343
}
4444
}
4545
}

geequel-shell/src/test/java/org/neo4j/shell/CypherShellTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.neo4j.driver.v1.summary.ResultSummary;
3131
import org.neo4j.shell.cli.CliArgHelper;
3232
import org.neo4j.shell.cli.CliArgs;
33+
import org.neo4j.shell.cli.NonInteractiveShellRunner;
3334
import org.neo4j.shell.cli.StringShellRunner;
3435
import org.neo4j.shell.commands.CommandExecutable;
3536
import org.neo4j.shell.commands.CommandHelper;
@@ -41,6 +42,8 @@
4142
import org.neo4j.shell.state.BoltStateHandler;
4243
import org.neo4j.shell.state.ListBoltResult;
4344

45+
import java.io.File;
46+
import java.io.FileOutputStream;
4447
import java.io.IOException;
4548
import java.util.Optional;
4649

@@ -281,6 +284,62 @@ public void specifyingACypherStringShouldGiveAStringRunner() throws IOException
281284
}
282285
}
283286

287+
288+
@Test
289+
public void specifyingACypherStringShouldAlwaysGiveAStringRunner() throws IOException {
290+
CliArgs cliArgs = CliArgHelper.parse("-f", "test-file", "MATCH (n) RETURN n ");
291+
292+
ConnectionConfig connectionConfig = mock(ConnectionConfig.class);
293+
294+
ShellRunner shellRunner = ShellRunner.getShellRunner(cliArgs, offlineTestShell, logger, connectionConfig);
295+
296+
if (!(shellRunner instanceof StringShellRunner)) {
297+
fail("Expected a different runner than: " + shellRunner.getClass().getSimpleName());
298+
}
299+
300+
cliArgs = CliArgHelper.parse("MATCH (n) RETURN n ", "-f", "test-file");
301+
302+
shellRunner = ShellRunner.getShellRunner(cliArgs, offlineTestShell, logger, connectionConfig);
303+
304+
if (!(shellRunner instanceof StringShellRunner)) {
305+
fail("Expected a different runner than: " + shellRunner.getClass().getSimpleName());
306+
}
307+
}
308+
309+
310+
@Test
311+
public void specifyingAFilePathShouldGiveANonInteractiveRunner() throws IOException {
312+
File file = File.createTempFile("test-file", ".cypher");
313+
file.deleteOnExit();
314+
FileOutputStream fos = new FileOutputStream(file);
315+
fos.write("RETURN 1;".getBytes());
316+
fos.close();
317+
CliArgs cliArgs = CliArgHelper.parse("-f", file.getAbsolutePath());
318+
319+
ConnectionConfig connectionConfig = mock(ConnectionConfig.class);
320+
321+
ShellRunner shellRunner = ShellRunner.getShellRunner(cliArgs, offlineTestShell, logger, connectionConfig);
322+
323+
if (!(shellRunner instanceof NonInteractiveShellRunner)) {
324+
fail("Expected a different runner than: " + shellRunner.getClass().getSimpleName());
325+
}
326+
}
327+
328+
@Test
329+
public void specifyingANonexistentFilePathShouldThrowAnError() throws IOException {
330+
CliArgs cliArgs = CliArgHelper.parse("-f", "test-file");
331+
332+
ConnectionConfig connectionConfig = mock(ConnectionConfig.class);
333+
334+
try {
335+
ShellRunner.getShellRunner(cliArgs, offlineTestShell, logger, connectionConfig);
336+
} catch (IOException e) {
337+
assertEquals("java.nio.file.NoSuchFileException: test-file", e.toString());
338+
return;
339+
}
340+
fail("Expected an exception to be thrown");
341+
}
342+
284343
@Test
285344
public void setParameterDoesNotTriggerByBoltError() throws CommandException {
286345
// given

geequel-shell/src/test/java/org/neo4j/shell/cli/CliArgsTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,18 @@ public void setCypher() throws Exception {
117117
cliArgs.setCypher(null);
118118
assertFalse(cliArgs.getCypher().isPresent());
119119
}
120+
121+
@Test
122+
public void setFile() throws Exception {
123+
// default
124+
assertFalse(cliArgs.getFile().isPresent());
125+
126+
cliArgs.setFile("foo");
127+
assertTrue(cliArgs.getFile().isPresent());
128+
//noinspection OptionalGetWithoutIsPresent
129+
assertEquals("foo", cliArgs.getFile().get());
130+
131+
cliArgs.setFile(null);
132+
assertFalse(cliArgs.getFile().isPresent());
133+
}
120134
}

0 commit comments

Comments
 (0)