Beispiel #1
0
// scanAnonEmbStructs expects a package and an index of structure in that package.
// It scans the structure looking for fields that are anonymously embedded types.
// If those types are from other packages, they are processed as well.
// As a result a list of all found types in a form of []parent is returned.
func (ps packages) scanAnonEmbStructs(pkg *reflect.Package, i int) (prs []parent) {
	// Iterating over fields of the structure.
	for j := range pkg.Structs[i].Fields {
		// Make sure current field is embedded anonymously,
		// i.e. there is no arg name.
		if pkg.Structs[i].Fields[j].Name != "" {
			continue
		}

		// Ensure the struct is embedded as a pointer.
		if !pkg.Structs[i].Fields[j].Type.Star {
			continue
		}

		// Add the field to the list of results.
		imp, _ := pkg.Imports.Value(pkg.Structs[i].File, pkg.Structs[i].Fields[j].Type.Package)
		p, _ := path.CleanImport(imp)
		prs = append(prs, parent{
			Import: p,
			Name:   pkg.Structs[i].Fields[j].Type.Name,
		})

		// Check whether this import has already been processed.
		// If not, do it now.
		if _, ok := ps[imp]; imp != "" && !ok {
			ps.processPackage(p)
		}
	}
	return
}
Beispiel #2
0
// Main is an entry point of the subcommand (tool).
func main(hs []tool.Handler, i int, args tool.Data) {
	// The first argument in the list is a path.
	// If it's missing use an empty string instead.
	p := args.GetDefault(0, "")

	// Prepare source and destination directory paths.
	src, err := path.ImportToAbsolute("github.com/colegion/goal/internal/skeleton")
	log.AssertNil(err)
	destImp, err := path.CleanImport(p)
	log.AssertNil(err)
	dest, err := path.ImportToAbsolute(destImp)
	log.AssertNil(err)

	// Make sure the requested import path (dest) does not exist yet.
	if _, err := os.Stat(dest); !os.IsNotExist(err) {
		log.Error.Panicf(`Cannot use "%s", such import path already exists.`, destImp)
	}

	// Scan the skeleton directory and get a list of directories / files
	// to be copied / processed.
	res, err := walk(src)
	log.AssertNil(err)

	// Create the directories in destination path.
	for i := 0; i < len(res.dirs); i++ {
		err = os.MkdirAll(filepath.Join(dest, res.dirs[i]), 0755)
		log.AssertNil(err)
	}

	// Copy static files to the destination directories.
	for i := 0; i < len(res.files); i++ {
		copyFile(res.files[i].absolute, filepath.Join(dest, res.files[i].relative))
	}

	// Process source files and copy to the destination directories.
	for i := 0; i < len(res.srcs); i++ {
		copyModifiedFile(
			res.srcs[i].absolute, filepath.Join(dest, res.srcs[i].relative), [][][]byte{
				{
					[]byte("github.com/colegion/goal/internal/skeleton"),
					[]byte(destImp),
				},
			},
		)
	}

	log.Info.Printf(info, destImp)
}
Beispiel #3
0
// main is an entry point of the "run" subcommand (tool).
func main(hs []tool.Handler, i int, args tool.Data) {
	// The first argument in the list is a path.
	// If it's missing use an empty string instead.
	p := args.GetDefault(0, "")

	// Determine import path and absolute path of the project to run.
	imp, err := path.CleanImport(p)
	log.AssertNil(err)
	dir, err := path.ImportToAbsolute(imp)
	log.AssertNil(err)

	// Prepare a path of configuration file.
	cf := filepath.Join(dir, ConfigFile)

	// Start a user tasks runner and instances controller.
	go instanceController()

	// Start a configuration file watcher.
	go configDaemon(imp, cf)

	// Show user friendly errors and terminate subprograms
	// in case of panics.
	defer func() {
		channel <- message{
			action: "exit",
		}
		<-stopped
		log.Trace.Panicln("Application has been terminated.")
	}()

	// Execute all commands from the requested directory.
	curr, _ := os.Getwd()
	os.Chdir(dir) // pushd
	defer func() {
		// Going back to the initial directory.
		os.Chdir(curr) // popd
	}()

	// Load the configuration.
	reloadConfig()

	// Cleaning up after we are done.
	signal.Notify(notify, os.Interrupt, syscall.SIGTERM)
	<-notify
}