예제 #1
0
파일: sync.go 프로젝트: Bowery/bowery-cli
// Upload sends the paths contents to the service compressed.
func (watcher *Watcher) Upload() error {
	var (
		err  error
		file *os.File
	)
	path := watcher.uploadPath()
	i := 0

	ignores, err := db.GetIgnores(watcher.Path)
	if err != nil {
		return watcher.wrapErr(err)
	}

	if watcher.Path != "" {
		upload, err := tar.Tar(watcher.Path, ignores)
		if err != nil {
			return watcher.wrapErr(err)
		}

		// Write the tgz file to read from.
		file, err = os.Create(path)
		if err != nil {
			return watcher.wrapErr(err)
		}
		defer os.RemoveAll(path)
		defer file.Close()

		// Copy the contents to the file.
		_, err = io.Copy(file, upload)
		if err != nil {
			return watcher.wrapErr(err)
		}
	}

	for i < 1000 {
		// If we've failed once, wait a bit.
		if err != nil {
			<-time.After(time.Millisecond * 50)
		}

		// Make sure we're at the beginning of the file.
		if watcher.Path != "" {
			_, err = file.Seek(0, os.SEEK_SET)
			if err != nil {
				return watcher.wrapErr(err)
			}
		}

		// Attempt to upload the file to the services satellite.
		err = delancey.Upload(watcher.Service.SatelliteAddr, watcher.Service.Name, file)
		if err == nil {
			return nil
		}

		i++
	}

	return watcher.wrapErr(err)
}
예제 #2
0
파일: sync.go 프로젝트: Bowery/bowery-cli
// Start handles file events and uploads the changes.
func (watcher *Watcher) Start(evChan chan *Event, errChan chan error) {
	if watcher.Path == "" {
		return
	}
	stats := make(map[string]os.FileInfo)
	found := make([]string, 0)

	ignores, err := db.GetIgnores(watcher.Path)
	if err != nil {
		errChan <- watcher.wrapErr(err)
		return
	}

	// Get initial stats.
	err = filepath.Walk(watcher.Path, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// Check if ignoring.
		for _, ignore := range ignores {
			if ignore == path {
				if info.IsDir() {
					return filepath.SkipDir
				}

				return nil
			}
		}

		stats[path] = info
		return nil
	})
	if err != nil {
		errChan <- watcher.wrapErr(err)
		return
	}

	// Manager updates/creates.
	walker := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		rel, err := filepath.Rel(watcher.Path, path)
		if err != nil {
			return err
		}

		// Check if ignoring.
		for _, ignore := range ignores {
			if ignore == path {
				for p := range stats {
					if p == path || strings.Contains(p, path+string(filepath.Separator)) {
						delete(stats, p)
					}
				}

				if info.IsDir() {
					return filepath.SkipDir
				}
				return nil
			}
		}
		pstat, ok := stats[path]
		status := ""

		// Check if created/updated.
		if ok && (info.ModTime().After(pstat.ModTime()) || info.Mode() != pstat.Mode()) {
			status = "update"
		} else if !ok {
			status = "create"
		}

		// Ignore directory changes, and no event status.
		if info.IsDir() || status == "" {
			stats[path] = info
			found = append(found, path)
			return nil
		}

		err = watcher.Update(rel, status)
		if err != nil {
			if os.IsNotExist(err) {
				log.Debug("Ignoring temp file", status, "event", rel)
				return nil
			}

			return err
		}

		evChan <- &Event{watcher.Service.Name, status, rel}
		stats[path] = info
		found = append(found, path)
		return nil
	}

	for {
		// Check if we're done.
		select {
		case <-watcher.done:
			return
		default:
		}

		ignores, err = db.GetIgnores(watcher.Path)
		if err != nil {
			errChan <- watcher.wrapErr(err)
			return
		}

		err = filepath.Walk(watcher.Path, walker)
		if err != nil {
			errChan <- watcher.wrapErr(err)
			return
		}

		// Check for deletes.
		for path := range stats {
			skip := false
			rel, err := filepath.Rel(watcher.Path, path)
			if err != nil {
				errChan <- watcher.wrapErr(err)
				return
			}

			for _, f := range found {
				if f == path {
					skip = true
					break
				}
			}

			if skip {
				continue
			}

			delete(stats, path)
			err = watcher.Update(rel, "delete")
			if err != nil {
				errChan <- watcher.wrapErr(err)
				return
			}

			evChan <- &Event{watcher.Service.Name, "delete", rel}
		}

		found = make([]string, 0)
		<-time.After(500 * time.Millisecond)
	}
}