示例#1
0
文件: cached.go 项目: sombr/ccat
// ReadCached reads a Tree's configuration from all of its source unit
// definition files (which may either be in a local VFS rooted at a
// .srclib-cache/<COMMITID> dir, or a remote VFS). It does not read
// the Srcfile; the Srcfile's directives are already accounted for in
// the cached source unit definition files.
//
// bdfs should be a VFS obtained from a call to
// (buildstore.RepoBuildStore).Commit.
func ReadCached(bdfs vfs.FileSystem) (*Tree, error) {
	if _, err := bdfs.Lstat("."); os.IsNotExist(err) {
		return nil, fmt.Errorf("build cache dir does not exist (did you run `src config` to create it)?")
	} else if err != nil {
		return nil, err
	}

	// Collect all **/*.unit.json files.
	var unitFiles []string
	unitSuffix := buildstore.DataTypeSuffix(unit.SourceUnit{})
	w := fs.WalkFS(".", rwvfs.Walkable(rwvfs.ReadOnly(bdfs)))
	for w.Step() {
		if err := w.Err(); err != nil {
			return nil, err
		}
		if path := w.Path(); strings.HasSuffix(path, unitSuffix) {
			unitFiles = append(unitFiles, path)
		}
	}

	// Parse units
	sort.Strings(unitFiles)
	units := make([]*unit.SourceUnit, len(unitFiles))
	par := parallel.NewRun(runtime.GOMAXPROCS(0))
	for i_, unitFile_ := range unitFiles {
		i, unitFile := i_, unitFile_
		par.Do(func() error {
			f, err := bdfs.Open(unitFile)
			if err != nil {
				return err
			}
			if err := json.NewDecoder(f).Decode(&units[i]); err != nil {
				f.Close()
				return err
			}
			if err := f.Close(); err != nil {
				return err
			}
			return nil
		})
	}
	if err := par.Wait(); err != nil {
		return nil, err
	}
	return &Tree{SourceUnits: units}, nil
}
示例#2
0
func uploadFile(local vfs.FileSystem, remote rwvfs.FileSystem, path string, fi os.FileInfo, dryRun bool) error {
	kb := float64(fi.Size()) / 1024
	if GlobalOpt.Verbose || dryRun {
		log.Printf("Uploading %s (%.1fkb)", path, kb)
	}
	if dryRun {
		return nil
	}

	lf, err := local.Open(path)
	if err != nil {
		return err
	}

	if err := rwvfs.MkdirAll(remote, filepath.Dir(path)); err != nil {
		return err
	}
	rf, err := remote.Create(path)
	if err != nil {
		return err
	}
	defer func() {
		if err := rf.Close(); err != nil {
			log.Println("Error closing after error:", err)
		}
	}()

	if _, err := io.Copy(rf, lf); err != nil {
		return err
	}

	if err := rf.Close(); err != nil {
		return err
	}

	if GlobalOpt.Verbose {
		log.Printf("Uploaded %s (%.1fkb)", path, kb)
	}
	return nil
}
示例#3
0
func fetchFile(remote vfs.FileSystem, local rwvfs.FileSystem, path string, fi os.FileInfo, dryRun bool) error {
	kb := float64(fi.Size()) / 1024
	if GlobalOpt.Verbose || dryRun {
		log.Printf("Fetching %s (%.1fkb)", path, kb)
	}
	if dryRun {
		return nil
	}

	if err := rwvfs.MkdirAll(local, filepath.Dir(path)); err != nil {
		return err
	}

	rf, err := remote.Open(path)
	if err != nil {
		return fmt.Errorf("remote file: %s", err)
	}
	defer rf.Close()

	lf, err := local.Create(path)
	if err != nil {
		return fmt.Errorf("local file: %s", err)
	}
	defer lf.Close()

	if _, err := io.Copy(lf, rf); err != nil {
		return fmt.Errorf("copy from remote to local: %s", err)
	}

	if GlobalOpt.Verbose {
		log.Printf("Fetched %s (%.1fkb)", path, kb)
	}

	if err := lf.Close(); err != nil {
		return fmt.Errorf("local file: %s", err)
	}
	return nil
}
示例#4
0
文件: fs.go 项目: sombr/ccat
// GetFileWithOptions gets a file and observes the options specified
// in opt. If fs implements FileGetter, fs.GetFileWithOptions is
// called; otherwise the options are applied on the client side after
// fetching the whole file.
func GetFileWithOptions(fs vfs.FileSystem, path string, opt GetFileOptions) (*FileWithRange, error) {
	if fg, ok := fs.(FileGetter); ok {
		return fg.GetFileWithOptions(path, opt)
	}

	fi, err := fs.Lstat(path)
	if err != nil {
		return nil, err
	}

	e := newTreeEntry(fi)
	fwr := FileWithRange{TreeEntry: e}

	if fi.Mode().IsDir() {
		entries, err := fs.ReadDir(path)
		if err != nil {
			return nil, err
		}

		e.Entries = make([]*TreeEntry, len(entries))
		for i, fi := range entries {
			e.Entries[i] = newTreeEntry(fi)
		}
		sort.Sort(TreeEntriesByTypeByName(e.Entries))
	} else if fi.Mode().IsRegular() {
		f, err := fs.Open(path)
		if err != nil {
			return nil, err
		}
		defer f.Close()

		contents, err := ioutil.ReadAll(f)
		if err != nil {
			return nil, err
		}

		e.Contents = contents

		if empty := (GetFileOptions{}); opt != empty {
			fr, _, err := ComputeFileRange(contents, opt)
			if err != nil {
				return nil, err
			}

			// Trim to only requested range.
			e.Contents = e.Contents[fr.StartByte:fr.EndByte]
			fwr.FileRange = *fr
		}
	}

	return &fwr, nil
}