github.com/ninadingole/gotest-ls@v0.0.3/main.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"flag"
     8  	"fmt"
     9  	"io"
    10  	"os"
    11  
    12  	"github.com/ninadingole/gotest-ls/pkg"
    13  )
    14  
    15  var (
    16  	// pretty is a flag to print the json output in a pretty format.
    17  	pretty = flag.Bool("p", false, "pretty print")
    18  
    19  	// file is a flag to specify a single file to parse.
    20  	file = flag.String("f", "", "file")
    21  
    22  	// help is a flag to print the help text.
    23  	help = flag.Bool("h", false, "help")
    24  )
    25  
    26  var (
    27  	// errPathIssue is the error message when the user provides both a file and a directory.
    28  	errPathIssue = errors.New("ERROR: cannot specify both a file and a directory")
    29  
    30  	// errNotAFile is the error message when the user provides a directory as a file.
    31  	errNotAFile = errors.New("ERROR: required file, provided directory")
    32  
    33  	// errUnknown is the error message when the error is not an expected type.
    34  	errUnknown = errors.New("ERROR: unknown error")
    35  )
    36  
    37  func main() {
    38  	flag.Usage = printHelpText(flag.CommandLine.Output())
    39  	flag.Parse()
    40  
    41  	err := Process(&args{
    42  		file:   *file,
    43  		dirs:   flag.Args(),
    44  		help:   *help,
    45  		pretty: *pretty,
    46  	}, os.Stdout)
    47  	if err != nil {
    48  		fmt.Println(err)
    49  		os.Exit(1)
    50  	}
    51  }
    52  
    53  // args is a struct that contains the arguments provided by the user.
    54  type args struct {
    55  	file   string
    56  	dirs   []string
    57  	help   bool
    58  	pretty bool
    59  }
    60  
    61  // Process is the main function that processes the arguments and prints the output.
    62  func Process(proc *args, writer io.Writer) error {
    63  	if requiresHelp(proc) {
    64  		printHelpText(writer)()
    65  
    66  		return nil
    67  	}
    68  
    69  	if err := validateArgs(proc); err != nil {
    70  		return err
    71  	}
    72  
    73  	if proc.file != "" {
    74  		proc.dirs = append(proc.dirs, proc.file)
    75  	}
    76  
    77  	tests, err := pkg.List(proc.dirs)
    78  	if err != nil {
    79  		return fmt.Errorf("%s: %w", errUnknown, err)
    80  	}
    81  
    82  	if len(tests) == 0 {
    83  		_, _ = writer.Write([]byte("No tests found\n"))
    84  
    85  		return nil
    86  	}
    87  
    88  	marshal, err := json.Marshal(tests)
    89  	if err != nil {
    90  		return fmt.Errorf("%s: %w", errUnknown, err)
    91  	}
    92  
    93  	if proc.pretty {
    94  		if err := prettyPrint(marshal, writer); err != nil {
    95  			return err
    96  		}
    97  	} else {
    98  		_, _ = writer.Write(marshal)
    99  	}
   100  
   101  	return nil
   102  }
   103  
   104  // validateArgs validates the arguments provided by the user.
   105  func validateArgs(args *args) error {
   106  	if args.file != "" && len(args.dirs) > 0 {
   107  		return errPathIssue
   108  	}
   109  
   110  	if args.file != "" {
   111  		stat, err := os.Stat(args.file)
   112  		if err != nil {
   113  			return fmt.Errorf("%s: %w", errUnknown, err)
   114  		}
   115  
   116  		if stat.IsDir() {
   117  			return errNotAFile
   118  		}
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  // requiresHelp checks if the user has requested help and not provided any required arguments.
   125  func requiresHelp(proc *args) bool {
   126  	return (len(proc.dirs) == 0 && proc.file == "") || proc.help
   127  }
   128  
   129  // prettyPrint prints the given json in a pretty format.
   130  func prettyPrint(data []byte, writer io.Writer) error {
   131  	var prettyJSON bytes.Buffer
   132  
   133  	err := json.Indent(&prettyJSON, data, "", "\t")
   134  	if err != nil {
   135  		return fmt.Errorf("%s: %w", errUnknown, err)
   136  	}
   137  
   138  	_, err = writer.Write(prettyJSON.Bytes())
   139  
   140  	return err
   141  }
   142  
   143  // printHelpText prints the help text for the program.
   144  func printHelpText(writer io.Writer) func() {
   145  	return func() {
   146  		writer := writer
   147  
   148  		_, _ = fmt.Fprintf(writer, `gotest-ls provides a list of all tests in a package or a file in JSON format.
   149  
   150  Usage:
   151    gotest-ls [flags] [directories]
   152  
   153  Examples:
   154  	gotest-ls .
   155   	gotest-ls -p ./cmd
   156   	gotest-ls -p ./cmd ./pkg
   157   	gotest-ls -f ./pkg/random_test.go
   158   	gotest-ls -p -f ./pkg/random_test.go
   159  
   160  Flags:
   161    -f, --file string   Path to a file, cannot be used with directories
   162    -h, --help          help for gotest-ls
   163    -p, --pretty        Pretty print the output in JSON format
   164  `)
   165  	}
   166  }