cmd

package
v0.0.0-...-94e6d93 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 4, 2023 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package main implements a simple CLI for the buildsys package

Index

Constants

This section is empty.

Variables

View Source
var RootCmd = &cobra.Command{
	Use:   "task [-l|-o] | [-nf] task1 task2 ...",
	Short: "Simple build system for Knossos",
	Long:  `This command parses the first tasks.star file it finds and executes the given tasks.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		taskArgs := make([]string, 0)
		options := make(map[string]string)
		dryRun, err := cmd.Flags().GetBool("dry")
		if err != nil {
			return eris.Wrap(err, "failed to check --dry flag")
		}

		force, err := cmd.Flags().GetBool("force")
		if err != nil {
			return eris.Wrap(err, "failed to check --force flag")
		}

		listTasks, err := cmd.Flags().GetBool("list")
		if err != nil {
			return eris.Wrap(err, "failed to check --list flag")
		}

		listOpts, err := cmd.Flags().GetBool("options")
		if err != nil {
			return eris.Wrap(err, "failed to check --options flag")
		}

		noDeps, err := cmd.Flags().GetBool("no-deps")
		if err != nil {
			return eris.Wrap(err, "failed to check --no-deps flag")
		}

		for _, part := range args {
			pos := strings.Index(part, "=")
			if pos > -1 {
				options[part[:pos]] = part[pos+1:]
			} else {
				taskArgs = append(taskArgs, part)
			}
		}

		logger := zerolog.New(NewConsoleWriter())
		ctx := context.Background()
		ctx = buildsys.WithLogger(ctx, &logger)

		if len(options) > 0 && (len(taskArgs) != 1 || taskArgs[0] != "configure") {
			logger.Fatal().Msg("Options can only be passed to the configure task")
		}

		wd, err := os.Getwd()
		if err != nil {
			logger.Fatal().Err(err).Msg("Failed to retrieve the current working directory")
		}

		path := wd
		var taskPath string
		for {
			taskPath = filepath.Join(path, "tasks.star")
			_, err := os.Stat(taskPath)
			if err == nil {
				break
			}
			if !eris.Is(err, os.ErrNotExist) {
				logger.Fatal().Err(err).Msgf("Failed to check %s", taskPath)
			}

			parent := filepath.Dir(path)
			if parent == path {
				logger.Fatal().Msg("No tasks.star file found")
			}

			path = parent
		}

		isConfigure := len(taskArgs) > 0 && taskArgs[0] == "configure"
		cacheFile := taskPath + ".cache"
		projectRoot := filepath.Dir(taskPath)
		var taskList buildsys.TaskList
		rebuildCache := isConfigure
		var cacheInfo fs.FileInfo

		if !rebuildCache {
			cacheInfo, err = os.Stat(cacheFile)
			if err != nil {
				if !eris.Is(err, os.ErrNotExist) {
					logger.Fatal().Err(err).Msg("Failed to check cache")
				}
			} else {
				scriptInfo, err := os.Stat(taskPath)
				if err != nil {
					logger.Fatal().Err(err).Msg("Failed to check task file")
				}

				if cacheInfo.ModTime().Sub(scriptInfo.ModTime()) < 0 {

					rebuildCache = true
				}
			}
		}

		if !isConfigure {
			var scriptFiles []string

			options, taskList, scriptFiles, err = buildsys.ReadCache(cacheFile)
			if err != nil && !eris.Is(err, os.ErrNotExist) && !eris.Is(err, io.EOF) {
				logger.Fatal().Err(err).Msg("Failed to open cache")
			}

			if scriptFiles == nil {

				rebuildCache = true
			} else {
				for _, path := range scriptFiles {
					info, err := os.Stat(path)
					if err != nil && !eris.Is(err, os.ErrNotExist) {
						logger.Fatal().Err(err).Msgf("Failed to check loaded script %s", path)
					}

					if info == nil || cacheInfo.ModTime().Sub(info.ModTime()) < 0 {

						rebuildCache = true
						break
					}
				}
			}
		}

		if rebuildCache || listOpts {
			var scriptOptions map[string]buildsys.ScriptOption
			var scriptFiles []string
			taskList, scriptOptions, scriptFiles, err = buildsys.RunScript(ctx, taskPath, filepath.Dir(taskPath), options, !listOpts)
			if err != nil {
				logger.Fatal().Err(err).Msg("Failed to parse tasks")
			}

			if listOpts {
				return printOptHelp(scriptOptions)
			}

			err = buildsys.WriteCache(cacheFile, options, taskList, scriptFiles)
			if err != nil {
				logger.Fatal().Err(err).Msg("Failed to cache processed tasks")
			}

			if isConfigure {
				logger.Info().Msg("Done")
				return nil
			}
		}

		if taskList == nil {
			logger.Fatal().Msg(
				`Please run "task configure" before you run any other task. For a list of available options, check` +
					` "task configure -o"`,
			)
		}

		if !listTasks {
			for _, name := range taskArgs {
				if noDeps {
					task, ok := taskList[name]

					if ok {
						task.Deps = make([]string, 0)
					}
				}

				err = buildsys.RunTask(ctx, projectRoot, name, taskList, dryRun, force)
				if err != nil {
					logger.Fatal().Err(err).Msgf("Failed task %s:", name)
				}
			}
		}

		if len(taskArgs) == 0 || listTasks {
			fmt.Println("Available tasks:")
			maxNameLen := 0
			sortedNames := make([]string, 0)
			for _, task := range taskList {
				if !task.Hidden {
					nameLen := len(task.Short)
					if nameLen > maxNameLen {
						maxNameLen = nameLen
					}

					sortedNames = append(sortedNames, task.Short)
				}
			}

			sort.Strings(sortedNames)

			lineFmt := fmt.Sprintf(" * %%-%ds %%s\n", maxNameLen+3)
			for _, name := range sortedNames {
				if !taskList[name].Hidden {
					fmt.Printf(lineFmt, name+":", taskList[name].Desc)
				}
			}
		}

		return nil
	},
}

Functions

This section is empty.

Types

type ConsoleWriter

type ConsoleWriter struct {
	// contains filtered or unexported fields
}

func NewConsoleWriter

func NewConsoleWriter() *ConsoleWriter

func (*ConsoleWriter) Write

func (w *ConsoleWriter) Write(p []byte) (n int, err error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL