Exemple #1
0
func (e *Event) packTarget(srcPath, name, destDir string, target setting.Target) (err error) {
	binName := name
	if target.GOOS == "windows" {
		binName += ".exe"
	}

	if err = os.MkdirAll(destDir, os.ModePerm); err != nil {
		return err
	}

	targetPath := path.Join(destDir, name+"_"+e.targetString(target))
	log.Debug("Packing target to: %s", targetPath)

	if err = os.RemoveAll(targetPath); err != nil {
		return err
	}

	zipPath := targetPath + ".zip"
	packPath := path.Join(targetPath, name)
	if err = os.MkdirAll(packPath, os.ModePerm); err != nil {
		return err
	}

	if err = os.Rename(path.Join(srcPath, binName), path.Join(packPath, binName)); err != nil {
		return err
	}

	// Pack resources.
	for _, resName := range setting.Resources {
		resPath := path.Join(srcPath, resName)
		destPath := path.Join(packPath, resName)
		if com.IsDir(resPath) {
			err = com.CopyDir(resPath, destPath)
		} else {
			err = com.Copy(resPath, destPath)
		}
		if err != nil {
			return err
		}
	}

	if err = zip.PackTo(targetPath, zipPath); err != nil {
		return err
	}

	os.RemoveAll(targetPath)
	return nil
}
Exemple #2
0
func notify(cmds [][]string) {
	runningLock.Lock()
	defer func() {
		runningCmd = nil
		runningLock.Unlock()
	}()

	for _, cmd := range cmds {
		command := exec.Command(cmd[0], cmd[1:]...)
		command.Stdout = os.Stdout
		command.Stderr = os.Stderr
		if err := command.Start(); err != nil {
			log.Error("Fail to start command %v - %v", cmd, err)
			fmt.Print("\x07")
			return
		}

		log.Debug("Running %v", cmd)
		runningCmd = command
		done := make(chan error)
		go func() {
			done <- command.Wait()
		}()

		isShutdown := false
		select {
		case err := <-done:
			if isShutdown {
				return
			} else if err != nil {
				log.Warn("Fail to execute command %v - %v", cmd, err)
				fmt.Print("\x07")
				return
			}
		case <-shutdown:
			isShutdown = true
			gracefulKill()
			return
		}
	}
	log.Info("Notify operations are done!")
}
Exemple #3
0
// getStatic gets a document from a statically known service.
// It returns ErrNoServiceMatch if the import path is not recognized.
func getStatic(importPath, etag string) (pdoc *Package, err error) {
	for _, s := range services {
		if s.get == nil || !strings.HasPrefix(importPath, s.prefix) {
			continue
		}
		m := s.pattern.FindStringSubmatch(importPath)
		if m == nil {
			if s.prefix != "" {
				log.Debug("Import path prefix matches known service, but regexp does not: %s", importPath)
				return nil, ErrInvalidRemotePath
			}
			continue
		}
		match := map[string]string{"importPath": importPath}
		for i, n := range s.pattern.SubexpNames() {
			if n != "" {
				match[n] = m[i]
			}
		}
		return s.get(match, etag)
	}
	return nil, ErrNoServiceMatch
}
Exemple #4
0
// CheckGoPackage checks package by import path.
func CheckPackage(importPath string, render macaron.Render, rt requestType) (*models.PkgInfo, error) {
	// Trim prefix of standard library.
	importPath = strings.TrimPrefix(importPath, "github.com/golang/go/tree/master/src")

	pinfo, err := models.GetPkgInfo(importPath)
	if rt != REQUEST_TYPE_REFRESH {
		if err == nil {
			fpath := setting.DocsGobPath + importPath + ".gob"
			if !setting.ProdMode && com.IsFile(fpath) {
				pdoc := new(Package)
				fr, err := os.Open(fpath)
				if err != nil {
					return nil, fmt.Errorf("read gob: %v", err)
				} else if err = gob.NewDecoder(fr).Decode(pdoc); err != nil {
					fr.Close()
					return nil, fmt.Errorf("decode gob: %v", err)
				}
				fr.Close()

				if err = renderDoc(render, pdoc, importPath); err != nil {
					return nil, fmt.Errorf("render cached doc: %v", err)
				}
			}

			pinfo.Views++
			if err = models.SavePkgInfo(pinfo); err != nil {
				return nil, fmt.Errorf("update views: %v", err)
			}
			return pinfo, nil
		}
	}

	// Just in case, should never happen.
	if err == models.ErrEmptyPackagePath {
		return nil, err
	}

	var etag string
	if err != models.ErrPackageVersionTooOld && pinfo != nil {
		etag = pinfo.Etag
	}

	// Fetch package from VCS.
	c := make(chan crawlResult, 1)
	go func() {
		pdoc, err := crawlDoc(importPath, etag)
		c <- crawlResult{pdoc, err}
	}()

	var pdoc *Package
	err = nil // Reset.
	select {
	case cr := <-c:
		if cr.err == nil {
			pdoc = cr.pdoc
		} else {
			err = cr.err
		}
	case <-time.After(setting.FetchTimeout):
		err = ErrFetchTimeout
	}

	if err != nil {
		if err == ErrPackageNotModified {
			log.Debug("Package has not been modified: %s", pinfo.ImportPath)
			// Update time so cannot refresh too often.
			pinfo.Created = time.Now().UTC().Unix()
			return pinfo, models.SavePkgInfo(pinfo)
		} else if err == ErrInvalidRemotePath {
			return nil, ErrInvalidRemotePath // Allow caller to make redirect to search.
		}
		return nil, fmt.Errorf("check package: %v", err)
	}

	if !setting.ProdMode {
		fpath := setting.DocsGobPath + importPath + ".gob"
		os.MkdirAll(path.Dir(fpath), os.ModePerm)
		fw, err := os.Create(fpath)
		if err != nil {
			return nil, fmt.Errorf("create gob: %v", err)
		}
		defer fw.Close()
		if err = gob.NewEncoder(fw).Encode(pdoc); err != nil {
			return nil, fmt.Errorf("encode gob: %v", err)
		}
	}

	log.Info("Walked package: %s, Goroutine #%d", pdoc.ImportPath, runtime.NumGoroutine())

	if err = renderDoc(render, pdoc, importPath); err != nil {
		return nil, fmt.Errorf("render doc: %v", err)
	}

	if pinfo != nil {
		pdoc.Id = pinfo.Id
	}

	pdoc.Created = time.Now().UTC().Unix()
	if err = models.SavePkgInfo(pdoc.PkgInfo); err != nil {
		return nil, fmt.Errorf("SavePkgInfo: %v", err)
	}

	return pdoc.PkgInfo, nil
}
Exemple #5
0
func runRun(ctx *cli.Context) {
	setup(ctx)

	go catchSignals()
	go notify(setting.Cfg.Run.InitCmds)

	watchPathes := append([]string{setting.WorkDir}, setting.Cfg.Run.WatchDirs...)
	if setting.Cfg.Run.WatchAll {
		subdirs := make([]string, 0, 10)
		for _, dir := range watchPathes[1:] {
			dirs, err := com.GetAllSubDirs(setting.UnpackPath(dir))
			if err != nil {
				log.Fatal("Fail to get sub-directories: %v", err)
			}
			for i := range dirs {
				if !setting.IgnoreDir(dirs[i]) {
					subdirs = append(subdirs, path.Join(dir, dirs[i]))
				}
			}
		}
		watchPathes = append(watchPathes, subdirs...)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal("Fail to create new watcher: %v", err)
	}
	defer watcher.Close()

	go func() {
		for {
			select {
			case e := <-watcher.Events:
				needsNotify := true

				if isTmpFile(e.Name) || !hasWatchExt(e.Name) || setting.IgnoreFile(e.Name) {
					continue
				}

				// Prevent duplicated builds.
				if lastBuild.Add(time.Duration(setting.Cfg.Run.BuildDelay) * time.Millisecond).
					After(time.Now()) {
					continue
				}
				lastBuild = time.Now()

				showName := e.String()
				if !log.NonColor {
					showName = strings.Replace(showName, setting.WorkDir, "\033[47;30m$WORKDIR\033[0m", 1)
				}

				if e.Op&fsnotify.Remove != fsnotify.Remove {
					mt, err := com.FileMTime(e.Name)
					if err != nil {
						log.Error("Fail to get file modify time: %v", err)
						continue
					}
					if eventTime[e.Name] == mt {
						log.Debug("Skipped %s", showName)
						needsNotify = false
					}
					eventTime[e.Name] = mt
				}

				if needsNotify {
					log.Info(showName)
					if runningCmd != nil && runningCmd.Process != nil {
						if runningCmd.Args[0] == "sudo" && runtime.GOOS == "linux" {
							// 给父进程发送一个TERM信号,试图杀死它和它的子进程
							rootCmd := exec.Command("sudo", "kill", "-TERM", com.ToStr(runningCmd.Process.Pid))
							rootCmd.Stdout = os.Stdout
							rootCmd.Stderr = os.Stderr
							if err := rootCmd.Run(); err != nil {
								log.Error("Fail to start rootCmd %s", err.Error())
								fmt.Print("\x07")
							}
						} else {
							shutdown <- true
						}
					}
					go notify(setting.Cfg.Run.Cmds)
				}
			}
		}
	}()

	log.Info("Following directories are monitored:")
	for i, p := range watchPathes {
		if err = watcher.Add(setting.UnpackPath(p)); err != nil {
			log.Fatal("Fail to watch diretory(%s): %v", p, err)
		}
		if i > 0 && !log.NonColor {
			p = strings.Replace(p, setting.WorkDir, "\033[47;30m$WORKDIR\033[0m", 1)
			p = strings.Replace(p, "$WORKDIR", "\033[47;30m$WORKDIR\033[0m", 1)
		}
		fmt.Printf("-> %s\n", p)
	}
	select {}
}
Exemple #6
0
func (e *Event) Build() {
	defer func() {
		log.Debug("Build finished: %s", e.Ref)
	}()

	// Fetch archive for reference.
	localPath := path.Join(setting.GOPATHSrc, path.Dir(setting.Repository.ImportPath))
	name := path.Base(setting.Repository.ImportPath)
	fullLocalPath := path.Join(localPath, name)

	defer os.RemoveAll(path.Join(setting.GOPATH, "bin"))

	// Start building targets.
	for _, target := range setting.Targets {
		envs := append([]string{
			"GOPATH=" + setting.GOPATH,
			"GOOS=" + target.GOOS,
			"GOARCH=" + target.GOARCH,
			"GOARM=" + target.GOARM,
		}, os.Environ()...)
		tags := setting.Cfg.Section("tags." + target.GOOS).Key("TAGS").MustString("")

		bufErr := new(bytes.Buffer)

		log.Debug("Getting dependencies: %s", e.targetString(target))
		cmd := exec.Command("go", "get", "-v", "-u", "-tags", tags, setting.Repository.ImportPath)
		cmd.Env = envs
		cmd.Stdout = os.Stdout
		cmd.Stderr = bufErr

		if err := cmd.Run(); err != nil {
			fmt.Println(bufErr.String())
			e.setError(fmt.Sprintf("Event.Build.(get dependencies): %s", bufErr.String()))
			return
		}

		log.Debug("Checking out branch: %s", e.Ref)
		cmd = exec.Command("git", "checkout", e.Ref)
		cmd.Env = envs
		cmd.Dir = fullLocalPath
		cmd.Stdout = os.Stdout
		cmd.Stderr = bufErr

		if err := cmd.Run(); err != nil {
			fmt.Println(bufErr.String())
			e.setError(fmt.Sprintf("Event.Build.(checkout branch): %s", bufErr.String()))
			return
		}

		log.Debug("Building target: %s", e.targetString(target))
		cmd = exec.Command("go", "build", "-v", "-tags", tags)
		cmd.Env = envs
		cmd.Dir = fullLocalPath
		cmd.Stdout = os.Stdout
		cmd.Stderr = bufErr

		if err := cmd.Run(); err != nil {
			fmt.Println(bufErr.String())
			e.setError(fmt.Sprintf("Event.Build.(build target): %s", bufErr.String()))
			return
		}

		if err := e.packTarget(fullLocalPath, name, setting.ArchivePath, target); err != nil {
			e.setError(fmt.Sprintf("Event.Build.packTarget: %v", err))
			return
		}

		targetName := name + "_" + e.targetString(target)
		for i := range Targets {
			if Targets[i].Name == targetName {
				Targets[i].LastBuild = time.Now()
				break
			}
		}
	}

	e.IsSucceed = true
	if _, err := x.Id(e.ID).AllCols().Update(e); err != nil {
		log.Error("Event.Build.Update: %v", err)
	}
}