//VFSStaticServer returns a StaticServer to serve a Godoc virtual file system //as defined in golang.org/x/tools/godoc/vfs . The Godoc vfs package contains //implementations for FileSystem, Map and Zip File based virtual file systems //Use errorHandlers to provide custom http.HandlerFunc to handle http.StatusNotFound //and http.StatusInternalServerError or provide nil to use default implementation //If a log.Logger is provided (ie. not nil), StaticServer does verbose logging func VFSStaticServer(f vfs.FileSystem, errorHandlers map[int]http.HandlerFunc, logger *log.Logger) StaticServer { return StaticServer{ stat: f.Lstat, readerfn: func(name string) (io.ReadSeeker, error) { rsc, err := f.Open(name) return io.ReadSeeker(rsc), err }, errorHandlers: setupErrorHandlers(errorHandlers), logger: logger, } }
func readJSONFileFS(fs vfs.FileSystem, file string, v interface{}) (err error) { f, err := fs.Open(file) if err != nil { return err } defer func() { err2 := f.Close() if err == nil { err = err2 } }() return json.NewDecoder(f).Decode(v) }
// 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 `srclib 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.Acquire() go func() { defer par.Release() f, err := bdfs.Open(unitFile) if err != nil { par.Error(err) return } if err := json.NewDecoder(f).Decode(&units[i]); err != nil { f.Close() par.Error(err) return } if err := f.Close(); err != nil { par.Error(err) return } }() } if err := par.Wait(); err != nil { return nil, err } return &Tree{SourceUnits: units}, nil }
// 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() { ee, err := readDir(fs, path, opt.RecurseSingleSubfolder, true) if err != nil { return nil, err } sort.Sort(TreeEntriesByTypeByName(ee)) e.Entries = ee } 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 }
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 }
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 }