Пример #1
0
func Shell() {
	sighup := autorestart.NotifyOnSighup()
	args, err := flags.ParseArgs(&Opts, os.Args[1:])
	if err != nil {
		err2, ok := err.(*flags.Error)
		if ok && err2.Type == flags.ErrHelp {
			return
		}
		alog.Printf("Error parsing command-line options: %s\n", err)
		return
	}
	if Opts.NoColor {
		alog.DisableColor()
	}
	ignorePart = stringset.New(filepath.SplitList(Opts.IgnorePart)...)
	ignoreSuffix = filepath.SplitList(Opts.IgnoreSuffix)
	ignoreSubstring = filepath.SplitList(Opts.IgnoreSubstring)
	deletePart = stringset.New(filepath.SplitList(Opts.DeletePart)...)
	deleteSuffix = filepath.SplitList(Opts.DeleteSuffix)
	deleteSubstring = filepath.SplitList(Opts.DeleteSubstring)
	if Opts.Child {
		if len(args) < 1 {
			alog.Fatalln("Not enough arguments, need 1")
		}
		RootPath = args[0]
		execChild()
		return
	}

	if len(args) < 2 {
		alog.Fatalln("Not enough arguments, need 2")
	}
	RootPath = args[0]
	remoteFullPath := args[1]
	remoteFullPathParts := strings.SplitN(remoteFullPath, ":", 2)
	remoteHost, remoteRoot := remoteFullPathParts[0], remoteFullPathParts[1]
	alog.Printf("@(dim:nsync started, syncing) @(cyan:%s) @(dim:to) @(cyan:%s)@(dim::)@(cyan:%s)\n", RootPath, remoteHost, remoteRoot)
	onChildExit := make(chan error)
	go connectChildForever(remoteHost, remoteRoot, onChildExit)
	go execParent()
	select {
	case <-sighup:
		killChildSshProcess()
	case <-onChildExit:
		// Restart everything if the child drops out (this is kludgy but effective)
	case <-time.After(20 * time.Minute):
		// Restart periodically, at least until I figure out what causes hangs
	}
}
Пример #2
0
func WatchExecutable(pathish string) (<-chan string, error) {
	exePath, err := getExePath(pathish)
	if err != nil {
		return nil, err
	}
	notify, err := WatchPath(exePath)
	if err != nil {
		return nil, err
	}
	debounced := make(chan string)
	go func() {
		pathsChanged := stringset.New()
		for {
			if pathsChanged.Len() > 0 {
				select {
				case pe := <-notify:
					pathsChanged.Add(pe.Path)
					break
				case <-time.After(400 * time.Millisecond):
					for _, p := range pathsChanged.All() {
						debounced <- p
					}
					pathsChanged.Clear()
				}
			} else {
				pathsChanged.Add((<-notify).Path)
			}
		}
	}()
	return debounced, nil
}
Пример #3
0
func (ctx *SyncContext) watchForChangesLocal(fileEventCallback func(string)) {
	status := ctx.NewLogger("watcher")
	listener := watcher.NewListener()
	listener.Path = ctx.syncPath
	listener.IgnorePart = stringset.New(".gut")
	err := listener.Start()
	status.BailIf(err)

	go func() {
		for pathEvent := range listener.NotifyChan {
			path := pathEvent.Path
			relPath, err := filepath.Rel(ctx.syncPath, path)
			if err != nil {
				status.Bail(err)
			}
			fileEventCallback(relPath)
		}
	}()
}
Пример #4
0
	"syscall",
	"archive",
	"archive/tar",
	"archive/tar/testdata",
	"archive/zip",
	"archive/zip/testdata",
	"html",
	"html/template",
	"hash",
	"hash/fnv",
	"hash/crc32",
	"hash/adler32",
	"hash/crc64",
	"bytes",
	"encoding",
	"encoding/gob",
	"encoding/hex",
	"encoding/csv",
	"encoding/json",
	"encoding/json/testdata",
	"encoding/binary",
	"encoding/asn1",
	"encoding/base32",
	"encoding/pem",
	"encoding/ascii85",
	"encoding/base64",
	"encoding/xml",
}

var goStdLibPackages = stringset.New(goStdLibPackagesSlice...)
Пример #5
0
func update(pkgName string) {
	pUpdate := NewPackage(pkgName)
	defer func() {
		updateFinished <- pUpdate
	}()
	pUpdate.UpdateStartTime = time.Now()

	absPkgPath := filepath.Join(srcRoot, pkgName)
	pkg, err := build.ImportDir(absPkgPath, build.ImportComment)
	if err != nil {
		pUpdate.UpdateError = err
		// If the directory no longer exists, then tell the dispatcher to remove this package from the index
		_, statErr := os.Stat(absPkgPath)
		if statErr != nil && os.IsNotExist(statErr) {
			pUpdate.RemovePackage = true
		} else if beVerbose() {
			alog.Printf("@(warn:Error parsing import of module %s: %s)\n", pkgName, err)
		}
		return
	}
	pUpdate.Imports = stringset.New()
	for _, importName := range pkg.Imports {
		if !goStdLibPackages.Has(importName) {
			pUpdate.Imports.Add(importName)
		}
	}
	statFiles := func(files []string) {
		for _, filename := range files {
			path := filepath.Join(absPkgPath, filename)
			fileinfo, err := os.Stat(path)
			if err != nil {
				alog.Printf("@(error:Error stat-ing %s: %v)\n", path, err)
				pUpdate.UpdateError = err
				return
			}
			modTime := fileinfo.ModTime()
			if modTime.After(pUpdate.UpdateStartTime) {
				if modTime.After(time.Now()) {
					alog.Printf("@(warn:File has future modification time: %q mod %s)\n", path, modTime.String())
					alog.Printf("@(warn:Correct triggering of builds depends on correctly-set system clocks.)\n")
					// Assume that it was not actually modified in the future, but that the system clock is just wrong
					// This will allow us to build the package, but we'll keep re-building every time autoinstall
					// restarts until the system clock gets past the file's time.
					modTime = pUpdate.UpdateStartTime.Add(-1 * time.Microsecond)
				}
			}
			if modTime.After(pUpdate.SourceModTime) {
				pUpdate.SourceModTime = modTime
				pUpdate.RecentSrcName = fileinfo.Name()
			}
		}
	}
	statFiles(pkg.GoFiles)
	statFiles(pkg.CgoFiles)
	statFiles(pkg.CFiles)
	statFiles(pkg.CXXFiles)
	statFiles(pkg.MFiles)
	statFiles(pkg.HFiles)
	statFiles(pkg.SFiles)
	statFiles(pkg.SwigFiles)
	statFiles(pkg.SwigCXXFiles)
	statFiles(pkg.SysoFiles)
	if shouldRunTests() {
		statFiles(pkg.TestGoFiles)
	}

	if len(pkg.TestGoFiles) > 0 {
		pUpdate.HasTests = true
	}
	pUpdate.IsProgram = pkg.Name == "main"

	targetPath := pUpdate.getAbsTargetPath()
	fileinfo, err := os.Stat(targetPath)
	if err != nil && !os.IsNotExist(err) {
		alog.Printf("@(error:Error stat-ing %s: %v)\n", targetPath, err)
		pUpdate.UpdateError = err
		return
	} else if err == nil {
		pUpdate.BuiltModTime = fileinfo.ModTime()
	}
}
Пример #6
0
func main() {
	sighup := autorestart.NotifyOnSighup()
	_, err := flags.ParseArgs(&Opts, os.Args)
	if err != nil {
		err2, ok := err.(*flags.Error)
		if ok && err2.Type == flags.ErrHelp {
			return
		}
		alog.Printf("Error parsing command-line options: %s\n", err)
		return
	}
	if goPath == "" {
		alog.Printf("GOPATH is not set in the environment. Please set GOPATH first, then retry.\n")
		alog.Printf("For help setting GOPATH, see https://golang.org/doc/code.html\n")
		return
	}
	if Opts.NoColor {
		alog.DisableColor()
	} else {
		alog.AddAnsiColorCode("time", alog.ColorBlue)
	}
	alog.Printf("@(dim:autoinstall started.)\n")
	if Opts.MaxWorkers == 0 {
		Opts.MaxWorkers = runtime.GOMAXPROCS(0)
	}
	pluralProcess := ""
	if Opts.MaxWorkers != 1 {
		pluralProcess = "es"
	}
	alog.Printf("@(dim:Building all packages in) @(dim,cyan:%s)@(dim: using up to )@(dim,cyan:%d)@(dim: process%s.)\n", goPath, Opts.MaxWorkers, pluralProcess)
	if !Opts.Verbose {
		alog.Printf("@(dim:Use) --verbose @(dim:to show all messages during startup.)\n")
	}

	listener := watcher.NewListener()
	listener.Path = srcRoot
	// "_workspace" is a kludge to avoid recursing into Godeps workspaces
	// "node_modules" is a kludge to avoid walking into typically-huge node_modules trees
	listener.IgnorePart = stringset.New(".git", ".hg", "node_modules", "_workspace", "etld")
	listener.NotifyOnStartup = true
	listener.DebounceDuration = 200 * time.Millisecond
	listener.Start()

	// Delete any straggler tmp files, carefully
	files, err := ioutil.ReadDir(tmpdir)
	if err == nil {
		for _, file := range files {
			if filepath.Ext(file.Name()) == ".tmp" {
				os.Remove(filepath.Join(tmpdir, file.Name()))
			}
		}
	} else if os.IsNotExist(err) {
		err = os.MkdirAll(tmpdir, 0700)
		if err != nil {
			alog.Printf("@(error:Error creating temp directory at %s: %v)\n", tmpdir, err)
			return
		}
	} else {
		alog.Printf("@(error:Error checking contents of temp directory at %s: %v)\n", tmpdir, err)
		return
	}

	go processPathTriggers(listener.NotifyChan)
	go dispatcher()

	<-sighup
	startupLogger.Close()
}
Пример #7
0
}

func printStartupSummary() {
	alog.Printf("@(dim:Finished initial pass of all packages.)\n")
	updateStartupText(true)
}

func beVerbose() bool {
	return finishedInitialPass || Opts.Verbose
}

func shouldRunTests() bool {
	return finishedInitialPass && Opts.RunTests
}

var buildExtensions = stringset.New(".go", ".c", ".cc", ".cxx", ".cpp", ".h", ".hh", ".hpp", ".hxx", ".s", ".swig", ".swigcxx", ".syso")

func processPathTriggers(notifyChan chan watcher.PathEvent) {
	for pathEvent := range notifyChan {
		path := pathEvent.Path
		moduleName, err := filepath.Rel(srcRoot, filepath.Dir(path))
		if err != nil {
			alog.Bail(err)
		}
		if buildExtensions.Has(filepath.Ext(path)) {
			if Opts.Verbose {
				alog.Printf("@(dim:Triggering module) @(cyan:%s) @(dim:due to update of) @(cyan:%s)\n", moduleName, path)
			}
			moduleUpdateChan <- moduleName
		}
	}