~sbinet/star-tex-patches

[PATCH star-tex 2/2] cmd/kpath-find: first import

Details
Message ID
<l6P5YKHeImIibeKojg7GHO8zo0eulkAEajcvx04q6jw@cp7-web-043.plabs.ch>
DKIM signature
missing
Download raw message
Patch: +185 -0
Signed-off-by: Sebastien Binet <s@sbinet.org>
---
 cmd/kpath-find/main.go      |  80 +++++++++++++++++++++++++++
 cmd/kpath-find/main_test.go | 105 ++++++++++++++++++++++++++++++++++++
 2 files changed, 185 insertions(+)
 create mode 100644 cmd/kpath-find/main.go
 create mode 100644 cmd/kpath-find/main_test.go

diff --git a/cmd/kpath-find/main.go b/cmd/kpath-find/main.go
new file mode 100644
index 0000000..4fdb083
--- /dev/null
+++ b/cmd/kpath-find/main.go
@@ -0,0 +1,80 @@
// Copyright ©2021 The star-tex Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Command kpath-find finds files in a TeX Directory Structure.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"git.sr.ht/~sbinet/star-tex/kpath"
)

func main() {
	log.SetPrefix("kpath-find: ")
	log.SetFlags(0)

	var (
		texmf = flag.String("texmf", "", "path to TEXMF distribution")
		all   = flag.Bool("all", false, "display all matches")
	)

	flag.Parse()

	if flag.NArg() <= 0 {
		flag.Usage()
		log.Fatalf("missing input file name")
	}

	if *texmf == "" {
	loop:
		for _, env := range []string{"TEXMF", "TEXMFROOT", "TEXMFDIST", "TEXMFHOME"} {
			v := os.Getenv(env)
			if v != "" {
				*texmf = v
				break loop
			}
		}
		if *texmf == "" {
			*texmf = "/usr/share/texmf-dist"
		}
	}

	dbname := filepath.Join(*texmf, "ls-R")
	xmain(flag.Arg(0), dbname, *all)
}

func xmain(name, dbname string, all bool) {
	fnames, err := process(name, dbname, all)
	if err != nil {
		log.Fatal(err)
	}
	for _, fname := range fnames {
		fmt.Printf("%s\n", fname)
	}
}

func process(name, dbname string, all bool) ([]string, error) {
	db, err := os.Open(dbname)
	if err != nil {
		return nil, fmt.Errorf("could not open texmf db %q: %w", dbname, err)
	}
	defer db.Close()

	ctx, err := kpath.NewFromDB(db)
	if err != nil {
		return nil, fmt.Errorf("could not create kpath context: %w", err)
	}

	if all {
		return ctx.FindAll(name)
	}

	fname, err := ctx.Find(name)
	return []string{fname}, err
}
diff --git a/cmd/kpath-find/main_test.go b/cmd/kpath-find/main_test.go
new file mode 100644
index 0000000..951fb21
--- /dev/null
+++ b/cmd/kpath-find/main_test.go
@@ -0,0 +1,105 @@
// Copyright ©2021 The star-tex Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func TestProcess(t *testing.T) {
	dir, err := os.MkdirTemp("", "kpath-find-")
	if err != nil {
		t.Fatalf("could not create tmp dir: %+v", err)
	}
	defer os.RemoveAll(dir)

	dbname := filepath.Join(dir, "ls-R")
	err = os.WriteFile(dbname, []byte(`%%
./:
./dir1:
file1.tex

./dir2:
file2.tex

./dir3:
file2.tex
`), 0755)
	if err != nil {
		t.Fatalf("could not create texmf db: %+v", err)
	}

	for _, tc := range []struct {
		name   string
		dbname string
		all    bool
		want   []string
		err    error
	}{
		{
			name:   "file1.tex",
			dbname: dbname,
			want:   []string{filepath.Join(dir, "/dir1/file1.tex")},
		},
		{
			name:   "file2.tex",
			dbname: dbname,
			all:    true,
			want: []string{
				filepath.Join(dir, "/dir2/file2.tex"),
				filepath.Join(dir, "/dir3/file2.tex"),
			},
		},
		{
			name:   "file2.tex",
			dbname: dbname,
			err:    fmt.Errorf(`kpath: too many hits for file "file2.tex" (n=2)`),
		},
		{
			name:   "file1.tex",
			dbname: dir,
			err: fmt.Errorf(
				`could not create kpath context: `+
					`kpath: could not parse db file: `+
					`could not scan db file: read %s: is a directory`,
				dir,
			),
		},
		{
			name:   "file1.tex",
			dbname: filepath.Join(dir, "not-there"),
			err: fmt.Errorf(
				`could not open texmf db %[1]q: `+
					`open %[1]s: no such file or directory`,
				filepath.Join(dir, "not-there"),
			),
		},
	} {
		t.Run(tc.name, func(t *testing.T) {
			got, err := process(tc.name, tc.dbname, tc.all)
			switch {
			case err == nil && tc.err == nil:
				// ok.
			case err != nil && tc.err != nil:
				if got, want := err.Error(), tc.err.Error(); got != want {
					t.Fatalf("invalid error:\ngot= %s\nwant=%s\n", got, want)
				}
				return
			case err != nil && tc.err == nil:
				t.Fatalf("could not run kpath-find: %+v", err)
			case err == nil && tc.err != nil:
				t.Fatalf("missing error. expected: %+v", tc.err)
			}

			if !reflect.DeepEqual(got, tc.want) {
				t.Fatalf("invalid file named:\ngot= %q\nwant=%q", got, tc.want)
			}
		})
	}
}
-- 
2.30.1
Reply to thread Export thread (mbox)