package source import ( "context" "fmt" "io/ioutil" "os" "strings" ) type LocalSource struct { root string } func NewLocal(root string) Source { return &LocalSource{ root: strings.TrimRight(root, "/"), } } func (s *LocalSource) resolve(path string) (string, error) { if !strings.HasPrefix(path, "//") { return "", fmt.Errorf("invalid path %q, expected // prefix", path) } path = path[2:] if strings.HasPrefix(path, "/") { return "", fmt.Errorf("invalid path %q, expected // prefix", path) } return s.root + "/" + path, nil } func (s *LocalSource) IsFile(ctx context.Context, path string) (bool, error) { path, err := s.resolve(path) if err != nil { return false, err } stat, err := os.Stat(path) if err != nil { if os.IsNotExist(err) { return false, nil } return false, fmt.Errorf("os.Stat(%q): %w", path, err) } return !stat.IsDir(), nil } func (s *LocalSource) ReadFile(ctx context.Context, path string) ([]byte, error) { path, err := s.resolve(path) if err != nil { return nil, err } // TODO(q3k): limit size return ioutil.ReadFile(path) } func (s *LocalSource) IsDirectory(ctx context.Context, path string) (bool, error) { path, err := s.resolve(path) if err != nil { return false, err } stat, err := os.Stat(path) if err != nil { if os.IsNotExist(err) { return false, nil } return false, fmt.Errorf("os.Stat(%q): %w", path, err) } return stat.IsDir(), nil } func (s *LocalSource) WebLinks(fpath string) []WebLink { gitURL := fmt.Sprintf(FlagGitwebURLPattern, "master", fpath) return []WebLink{ WebLink{Kind: "source", LinkLabel: "master", LinkURL: gitURL}, } }