Loading main.go +20 −23 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ import ( //go:embed max_releases.json var fallbackReleases []byte const version = "0.3.1" const version = "0.3.2" const maxConfigFile = "config.xml" const baseXDistro = "https://files.basex.org/releases/11.7/BaseX117.zip" Loading Loading @@ -2303,7 +2303,8 @@ func runFeed(feedPath, directory string, verbose bool) error { } if stat.Mode().IsRegular() { cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", fmt.Sprintf("db:put('max', '%s', '%s')", feedAbs, filepath.Base(feedAbs))) query := fmt.Sprintf("db:put('max', '%s', '%s')", feedAbs, filepath.Base(feedAbs)) cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", query) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if verbose { Loading @@ -2313,27 +2314,23 @@ func runFeed(feedPath, directory string, verbose bool) error { return cmd.Run() } offset := len(feedAbs) return filepath.WalkDir(feedAbs, func(p string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { return nil } if strings.ToLower(filepath.Ext(p)) != ".xml" { return nil } rel := p[offset:] cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", fmt.Sprintf("db:put('max', '%s', '%s')", p, rel)) feedDir := ensureTrailingPathSeparator(feedAbs) query := fmt.Sprintf("db:put('max', '%s', '')", feedDir) cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", query) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if verbose { fmt.Println(formatCommand(cmd)) } fmt.Println(p) fmt.Println(feedDir) return cmd.Run() }) } func ensureTrailingPathSeparator(path string) string { if strings.HasSuffix(path, string(os.PathSeparator)) { return path } return path + string(os.PathSeparator) } func formatCommand(cmd *exec.Cmd) string { Loading main_test.go +129 −0 Original line number Diff line number Diff line Loading @@ -2,7 +2,9 @@ package main import ( "archive/tar" "bufio" "compress/gzip" "fmt" "net/url" "os" "path/filepath" Loading Loading @@ -158,3 +160,130 @@ func TestExtractTarGzPreservesExecutableBit(t *testing.T) { t.Fatalf("expected executable mode on %s, got %v", extracted, info.Mode()) } } func TestFeedCommandRunsForFileAndDirectory(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("test uses a shell script as fake bundled java") } tmpHome := t.TempDir() prevHome := userMaxDir prevCache := cacheDir userMaxDir = tmpHome cacheDir = filepath.Join(userMaxDir, "cache") t.Cleanup(func() { userMaxDir = prevHome cacheDir = prevCache }) oldWD, err := os.Getwd() if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = os.Chdir(oldWD) }) projectDir := filepath.Join(t.TempDir(), "project") if err := os.MkdirAll(projectDir, 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(projectDir, maxConfigFile), []byte(configInitTemplate), 0o644); err != nil { t.Fatal(err) } feedFile := filepath.Join(projectDir, "single.xml") if err := os.WriteFile(feedFile, []byte("<root/>"), 0o644); err != nil { t.Fatal(err) } feedDir := filepath.Join(projectDir, "batch") if err := os.MkdirAll(feedDir, 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(feedDir, "a.xml"), []byte("<a/>"), 0o644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(feedDir, "b.xml"), []byte("<b/>"), 0o644); err != nil { t.Fatal(err) } logPath := filepath.Join(t.TempDir(), "java.log") t.Setenv("CLIMAX_TEST_JAVA_LOG", logPath) if err := installFakeBundledJava(tmpHome); err != nil { t.Fatal(err) } root := newRootCmd() root.SetArgs([]string{"feed", feedFile, "--directory", projectDir}) if err := root.Execute(); err != nil { t.Fatalf("feed command failed for file input: %v", err) } root = newRootCmd() root.SetArgs([]string{"feed", feedDir, "--directory", projectDir}) if err := root.Execute(); err != nil { t.Fatalf("feed command failed for directory input: %v", err) } lines, err := readLogLines(logPath) if err != nil { t.Fatal(err) } if len(lines) != 4 { t.Fatalf("expected 4 java invocations (2 per feed run), got %d:\n%v", len(lines), lines) } createDBQuery := "if(not(db:exists('max'))) then db:create('max') else ()" if !strings.Contains(lines[0], createDBQuery) || !strings.Contains(lines[2], createDBQuery) { t.Fatalf("expected create-db query in first and third invocation, got:\n%v", lines) } if !strings.Contains(lines[1], fmt.Sprintf("db:put('max', '%s', '%s')", feedFile, filepath.Base(feedFile))) { t.Fatalf("expected single-file db:put query in second invocation, got:\n%s", lines[1]) } feedDirWithSep := ensureTrailingPathSeparator(feedDir) if !strings.Contains(lines[3], fmt.Sprintf("db:put('max', '%s', '')", feedDirWithSep)) { t.Fatalf("expected directory db:put query in fourth invocation, got:\n%s", lines[3]) } if strings.Contains(lines[3], "a.xml") || strings.Contains(lines[3], "b.xml") { t.Fatalf("expected no per-file db:put during directory feed, got:\n%s", lines[3]) } } func installFakeBundledJava(home string) error { javaBin := bundledJavaPath(filepath.Join(home, "jdk"), currentSystem()) if javaBin == "" { return fmt.Errorf("no bundled java path for system %s", currentSystem()) } if err := os.MkdirAll(filepath.Dir(javaBin), 0o755); err != nil { return err } script := "#!/bin/sh\n" + "if [ -n \"$CLIMAX_TEST_JAVA_LOG\" ]; then\n" + " printf '%s\\n' \"$*\" >> \"$CLIMAX_TEST_JAVA_LOG\"\n" + "fi\n" return os.WriteFile(javaBin, []byte(script), 0o755) } func readLogLines(path string) ([]string, error) { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() var lines []string scanner := bufio.NewScanner(f) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line != "" { lines = append(lines, line) } } if err := scanner.Err(); err != nil { return nil, err } return lines, nil } Loading
main.go +20 −23 Original line number Diff line number Diff line Loading @@ -43,7 +43,7 @@ import ( //go:embed max_releases.json var fallbackReleases []byte const version = "0.3.1" const version = "0.3.2" const maxConfigFile = "config.xml" const baseXDistro = "https://files.basex.org/releases/11.7/BaseX117.zip" Loading Loading @@ -2303,7 +2303,8 @@ func runFeed(feedPath, directory string, verbose bool) error { } if stat.Mode().IsRegular() { cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", fmt.Sprintf("db:put('max', '%s', '%s')", feedAbs, filepath.Base(feedAbs))) query := fmt.Sprintf("db:put('max', '%s', '%s')", feedAbs, filepath.Base(feedAbs)) cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", query) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if verbose { Loading @@ -2313,27 +2314,23 @@ func runFeed(feedPath, directory string, verbose bool) error { return cmd.Run() } offset := len(feedAbs) return filepath.WalkDir(feedAbs, func(p string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { return nil } if strings.ToLower(filepath.Ext(p)) != ".xml" { return nil } rel := p[offset:] cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", fmt.Sprintf("db:put('max', '%s', '%s')", p, rel)) feedDir := ensureTrailingPathSeparator(feedAbs) query := fmt.Sprintf("db:put('max', '%s', '')", feedDir) cmd := exec.Command(javaBin, "-cp", cpPaths(abs), "-Xmx2g", "org.basex.BaseX", query) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if verbose { fmt.Println(formatCommand(cmd)) } fmt.Println(p) fmt.Println(feedDir) return cmd.Run() }) } func ensureTrailingPathSeparator(path string) string { if strings.HasSuffix(path, string(os.PathSeparator)) { return path } return path + string(os.PathSeparator) } func formatCommand(cmd *exec.Cmd) string { Loading
main_test.go +129 −0 Original line number Diff line number Diff line Loading @@ -2,7 +2,9 @@ package main import ( "archive/tar" "bufio" "compress/gzip" "fmt" "net/url" "os" "path/filepath" Loading Loading @@ -158,3 +160,130 @@ func TestExtractTarGzPreservesExecutableBit(t *testing.T) { t.Fatalf("expected executable mode on %s, got %v", extracted, info.Mode()) } } func TestFeedCommandRunsForFileAndDirectory(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("test uses a shell script as fake bundled java") } tmpHome := t.TempDir() prevHome := userMaxDir prevCache := cacheDir userMaxDir = tmpHome cacheDir = filepath.Join(userMaxDir, "cache") t.Cleanup(func() { userMaxDir = prevHome cacheDir = prevCache }) oldWD, err := os.Getwd() if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = os.Chdir(oldWD) }) projectDir := filepath.Join(t.TempDir(), "project") if err := os.MkdirAll(projectDir, 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(projectDir, maxConfigFile), []byte(configInitTemplate), 0o644); err != nil { t.Fatal(err) } feedFile := filepath.Join(projectDir, "single.xml") if err := os.WriteFile(feedFile, []byte("<root/>"), 0o644); err != nil { t.Fatal(err) } feedDir := filepath.Join(projectDir, "batch") if err := os.MkdirAll(feedDir, 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(feedDir, "a.xml"), []byte("<a/>"), 0o644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(feedDir, "b.xml"), []byte("<b/>"), 0o644); err != nil { t.Fatal(err) } logPath := filepath.Join(t.TempDir(), "java.log") t.Setenv("CLIMAX_TEST_JAVA_LOG", logPath) if err := installFakeBundledJava(tmpHome); err != nil { t.Fatal(err) } root := newRootCmd() root.SetArgs([]string{"feed", feedFile, "--directory", projectDir}) if err := root.Execute(); err != nil { t.Fatalf("feed command failed for file input: %v", err) } root = newRootCmd() root.SetArgs([]string{"feed", feedDir, "--directory", projectDir}) if err := root.Execute(); err != nil { t.Fatalf("feed command failed for directory input: %v", err) } lines, err := readLogLines(logPath) if err != nil { t.Fatal(err) } if len(lines) != 4 { t.Fatalf("expected 4 java invocations (2 per feed run), got %d:\n%v", len(lines), lines) } createDBQuery := "if(not(db:exists('max'))) then db:create('max') else ()" if !strings.Contains(lines[0], createDBQuery) || !strings.Contains(lines[2], createDBQuery) { t.Fatalf("expected create-db query in first and third invocation, got:\n%v", lines) } if !strings.Contains(lines[1], fmt.Sprintf("db:put('max', '%s', '%s')", feedFile, filepath.Base(feedFile))) { t.Fatalf("expected single-file db:put query in second invocation, got:\n%s", lines[1]) } feedDirWithSep := ensureTrailingPathSeparator(feedDir) if !strings.Contains(lines[3], fmt.Sprintf("db:put('max', '%s', '')", feedDirWithSep)) { t.Fatalf("expected directory db:put query in fourth invocation, got:\n%s", lines[3]) } if strings.Contains(lines[3], "a.xml") || strings.Contains(lines[3], "b.xml") { t.Fatalf("expected no per-file db:put during directory feed, got:\n%s", lines[3]) } } func installFakeBundledJava(home string) error { javaBin := bundledJavaPath(filepath.Join(home, "jdk"), currentSystem()) if javaBin == "" { return fmt.Errorf("no bundled java path for system %s", currentSystem()) } if err := os.MkdirAll(filepath.Dir(javaBin), 0o755); err != nil { return err } script := "#!/bin/sh\n" + "if [ -n \"$CLIMAX_TEST_JAVA_LOG\" ]; then\n" + " printf '%s\\n' \"$*\" >> \"$CLIMAX_TEST_JAVA_LOG\"\n" + "fi\n" return os.WriteFile(javaBin, []byte(script), 0o755) } func readLogLines(path string) ([]string, error) { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() var lines []string scanner := bufio.NewScanner(f) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line != "" { lines = append(lines, line) } } if err := scanner.Err(); err != nil { return nil, err } return lines, nil }