Skip to content

Commit

Permalink
fix: can now use globbing for --sources
Browse files Browse the repository at this point in the history
Besides that it's now also possible to use absolute paths together
with globbing.
  • Loading branch information
quintesse committed May 13, 2022
1 parent d05dced commit f526a7d
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 18 deletions.
2 changes: 2 additions & 0 deletions src/main/java/dev/jbang/source/RunContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import dev.jbang.source.resolvers.AliasResourceResolver;
import dev.jbang.util.JavaUtil;
import dev.jbang.util.PropertiesValueResolver;
import dev.jbang.util.Util;

/**
* This class contains all the extra information needed to actually run a
Expand Down Expand Up @@ -421,6 +422,7 @@ private List<Source> allToScriptSource(List<String> sources) {
Function<String, String> propsResolver = it -> PropertiesValueResolver.replaceProperties(it,
getContextProperties());
return sources .stream()
.flatMap(line -> Util.explode(null, Util.getCwd(), line).stream())
.map(s -> resolveChecked(resolver, s))
.map(ref -> Source.forResourceRef(ref, propsResolver))
.collect(Collectors.toList());
Expand Down
69 changes: 51 additions & 18 deletions src/main/java/dev/jbang/util/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,46 +188,63 @@ static private boolean isPattern(String pattern) {
}

/**
* Explodes filepattern found in baseDir returnin list of relative Path names.
* Explodes filePattern found in baseDir returning list of relative Path names.
*
* TODO: this really should return some kind of abstraction of paths that allow
* it be portable for urls as wells as files...or have a filesystem for each...
*
* @param source
* @param baseDir
* @param filepattern
* @param filePattern
* @return
*/
public static List<String> explode(String source, Path baseDir, String filepattern) {

public static List<String> explode(String source, Path baseDir, String filePattern) {
List<String> results = new ArrayList<>();

if (source != null && Util.isURL(source)) {
// if url then just return it back for others to resolve.
// TODO: technically this is really where it should get resolved!
if (isPattern(filepattern)) {
Util.warnMsg("Pattern " + filepattern + " used while using URL to run; this could result in errors.");
if (isPattern(filePattern)) {
Util.warnMsg("Pattern " + filePattern + " used while using URL to run; this could result in errors.");
return results;
} else {
results.add(filepattern);
results.add(filePattern);
}
} else if (Util.isURL(filepattern)) {
results.add(filepattern);
} else if (!filepattern.contains("?") && !filepattern.contains("*")) {
} else if (Util.isURL(filePattern)) {
results.add(filePattern);
} else if (!filePattern.contains("?") && !filePattern.contains("*")) {
// not a pattern thus just as well return path directly
results.add(filepattern);
results.add(filePattern);
} else {
// it is a non-url letls try locate it
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + filepattern);
// it is a non-url let's try to locate it
final Path bd;
final boolean useAbsPath;
Path base = basePathWithoutPattern(filePattern);
String fp;
if (base.isAbsolute()) {
bd = base;
fp = filePattern.substring(bd.toString().length() + 1);
useAbsPath = true;
} else {
bd = baseDir;
fp = filePattern;
useAbsPath = false;
}
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + fp);

FileVisitor<Path> matcherVisitor = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attribs) {
Path relpath = baseDir.relativize(file);
Path relpath = bd.relativize(file);
if (matcher.matches(relpath)) {
// to avoid windows fail.
if (file.toFile().exists()) {
results.add(relpath.toString().replace("\\", "/"));
Path p = useAbsPath ? file : relpath;
if (isWindows()) {
results.add(p.toString().replace("\\", "/"));
} else {
results.add(p.toString());
}
} else {
Util.verboseMsg("Warning: " + relpath + " matches but does not exist!");
}
Expand All @@ -237,15 +254,31 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attribs) {
};

try {
Files.walkFileTree(baseDir, matcherVisitor);
Files.walkFileTree(bd, matcherVisitor);
} catch (IOException e) {
throw new ExitException(BaseCommand.EXIT_INTERNAL_ERROR,
"Problem looking for " + filepattern + " in " + baseDir.toString(), e);
throw new ExitException(BaseCommand.EXIT_INTERNAL_ERROR, "Problem looking for " + fp + " in " + bd, e);
}
}
return results;
}

private static Path basePathWithoutPattern(String path) {
int p1 = path.indexOf('?');
int p2 = path.indexOf('*');
int pp = p1 < 0 ? p2 : (p2 < 0 ? p1 : Math.min(p1, p2));
if (pp >= 0) {
String npath = Util.isWindows() ? path.replace('\\', '/') : path;
int ps = npath.lastIndexOf('/', pp);
if (ps >= 0) {
return Paths.get(path.substring(0, ps + 1));
} else {
return Paths.get("");
}
} else {
return Paths.get(path);
}
}

/**
* @param name script name
* @return camel case of kebab string if name does not end with .java or .jsh
Expand Down
46 changes: 46 additions & 0 deletions src/test/java/dev/jbang/cli/TestRun.java
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,52 @@ protected void runCompiler(List<String> optionList)
}.setFresh(true).build();
}

@Test
void testAdditionalSourcesGlobbing() throws IOException {
Util.setCwd(examplesTestFolder);
String mainFile = examplesTestFolder.resolve("foo.java").toString();
String incFile = examplesTestFolder.resolve("bar/Bar.java").toString();

CommandLine.ParseResult pr = JBang.getCommandLine().parseArgs("build", "-s", "bar/*.java", "foo.java");
Build build = (Build) pr.subcommand().commandSpec().userObject();

RunContext ctx = build.getRunContext();
SourceSet ss = (SourceSet) ctx.forResource(mainFile);

new JavaBuilder(ss, ctx) {
@Override
protected void runCompiler(List<String> optionList)
throws IOException {
assertThat(optionList, hasItem(mainFile));
assertThat(optionList, hasItem(incFile));
// Skip the compiler
}
}.setFresh(true).build();
}

@Test
void testAdditionalSourcesAbsGlobbing() throws IOException {
String mainFile = examplesTestFolder.resolve("foo.java").toString();
String incGlob = examplesTestFolder.resolve("bar").toString() + File.separatorChar + "*.java";
String incFile = examplesTestFolder.resolve("bar/Bar.java").toString();

CommandLine.ParseResult pr = JBang.getCommandLine().parseArgs("build", "-s", incGlob, mainFile);
Build build = (Build) pr.subcommand().commandSpec().userObject();

RunContext ctx = build.getRunContext();
SourceSet ss = (SourceSet) ctx.forResource(mainFile);

new JavaBuilder(ss, ctx) {
@Override
protected void runCompiler(List<String> optionList)
throws IOException {
assertThat(optionList, hasItem(mainFile));
assertThat(optionList, hasItem(incFile));
// Skip the compiler
}
}.setFresh(true).build();
}

WireMockServer wms;

@BeforeEach
Expand Down
28 changes: 28 additions & 0 deletions src/test/java/dev/jbang/util/TestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,34 @@ void testExplode() throws IOException {

}

@Test
void testExplodeAbs() throws IOException {
Path baseDir = examplesTestFolder;

String source = ".";
String dir = examplesTestFolder.toString().replace('\\', '/');

final List<String> p = Util.explode(source, cwdDir, dir + "/**.java");

assertThat(p, hasItem(dir + "/res/resource.java"));
assertThat(p, not(hasItem(dir + "/hello.jsh")));
assertThat(p, hasItem(dir + "/quote.java"));

p.clear();
p.addAll(Util.explode(source, cwdDir, dir + "/**/*.java"));

assertThat(p, hasItem(dir + "/res/resource.java"));
assertThat(p, not(hasItem(dir + "/quote.java")));
assertThat(p, not(hasItem(dir + "/main.jsh")));

p.clear();
p.addAll(Util.explode(source, cwdDir, dir + "/res/resource.java"));

assertThat(p, containsInAnyOrder(dir + "/res/resource.java"));
assertThat(p, not(hasItem(dir + "/test.java")));

}

@Test
void testDispostionFilename() {
assertThat(Util.getDispositionFilename("inline; filename=token"), equalTo("token"));
Expand Down

0 comments on commit f526a7d

Please sign in to comment.