func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486 root, err := filepath.EvalSymlinks(runtime.GOROOT()) if err != nil { t.Fatal(err) } lib := filepath.Join(root, "lib") src := filepath.Join(root, "src") seenSrc := false walker := fs.Walk(root) for walker.Step() { if walker.Err() != nil { t.Fatal(walker.Err()) } switch walker.Path() { case lib: walker.SkipDir() case src: seenSrc = true } } if !seenSrc { t.Fatalf("%q not seen", src) } }
func ExampleWalker() { walker := fs.Walk("/usr/lib") for walker.Step() { if err := walker.Err(); err != nil { fmt.Fprintln(os.Stderr, err) continue } fmt.Println(walker.Path()) } }
func (c *LintCmd) Execute(args []string) error { if len(c.Args.Paths) == 0 { c.Args.Paths = []string{"."} } issuec := make(chan string) quitc := make(chan struct{}) go func() { for { select { case issue := <-issuec: fmt.Println(issue) case <-quitc: return } } }() lrepo, lrepoErr := openLocalRepo() if lrepoErr != nil { log.Printf("warning: while opening current dir's repo: %s", lrepoErr) } var wg sync.WaitGroup for _, path := range c.Args.Paths { w := fs.Walk(path) for w.Step() { if err := w.Err(); err != nil { return err } if fi := w.Stat(); fi.Mode().IsRegular() { suffix, typ := buildstore.DataType(fi.Name()) if suffix != "" { absPath, err := filepath.Abs(w.Path()) if err != nil { return err } var unitType, unitName string if !c.NoCheckResolve { if !strings.Contains(absPath, buildstore.BuildDataDirName) { return fmt.Errorf("couldn't infer which source unit %s corresponds to, because its absolute path is not under any %s dir; either run with --no-check-resolve to skip checking that internal refs resolve to valid defs (which requires knowing what source unit each output file is from), or run 'src lint' against .srclib-cache or subdirectories of it", w.Path(), buildstore.BuildDataDirName) } unitType = strings.TrimSuffix(fi.Name(), "."+suffix+".json") // Infer source unit name from file path (the // path components after .srclib-cache until // the basename). pcs := strings.Split(absPath, string(os.PathSeparator)) for i, pc := range pcs { if pc == buildstore.BuildDataDirName && len(pcs) > i+2 { unitName = filepath.Clean(strings.Join(pcs[i+2:len(pcs)-1], "/")) break } } } var commitID string if !c.NoCheckFiles { // Infer commit ID from file path (the path component after .srclib-cache). pcs := strings.Split(absPath, string(os.PathSeparator)) for i, pc := range pcs { if pc == buildstore.BuildDataDirName && len(pcs) > i+1 { commitID = pcs[i+1] break } } } if commitID == "" && !c.NoCheckFiles { return fmt.Errorf("couldn't infer which commit ID %s was built from, which is necessary to check that file/dir fields refer to actual files; either run with --no-check-files to skip the file/dir check or pass paths that contain '.../.srclib-cache/COMMITID/...' (which allows this command to infer the commit ID)", w.Path()) } // Ensure that commitID matches the local repo's commit ID. if commitID != "" && !c.NoCheckFiles { if lrepo != nil && lrepo.CommitID != commitID { return fmt.Errorf("%s was built from commit %s, but the current repo working tree HEAD is commit %s; these must be the same to check that file/dir fields refer to actual files in the repo that their specific commit, so you must either (1) only run lint against build data files for commit %s; (2) run with --no-check-files to skip the file/dir check; or (3) check out commit %s in this repo", w.Path(), commitID, lrepo.CommitID, lrepo.CommitID, commitID) } } checkFilesExist := !c.NoCheckFiles wg.Add(1) go func(path string) { defer wg.Done() var issues []string var err error switch typ.(type) { case unit.SourceUnit: issues, err = lintSourceUnit(lrepo.RootDir, path, checkFilesExist) case *graph.Output: issues, err = lintGraphOutput(lrepo.RootDir, c.Repo, unitType, unitName, path, checkFilesExist) case []*dep.ResolvedDep: issues, err = lintDepresolveOutput(lrepo.RootDir, path, checkFilesExist) } for _, issue := range prependLabelToStrings(path, issues) { issuec <- issue } if err != nil { log.Fatalf(redbg("ERR")+" %s: %s", path, err) } }(w.Path()) } } } } wg.Wait() close(quitc) return nil }
func TestWalk(t *testing.T) { makeTree(t) errors := make([]error, 0, 10) clear := true markFn := func(walker *fs.Walker) (err error) { for walker.Step() { err = mark(walker.Path(), walker.Stat(), walker.Err(), &errors, clear) if err != nil { break } } return err } // Expect no errors. err := markFn(fs.Walk(tree.name)) if err != nil { t.Fatalf("no error expected, found: %s", err) } if len(errors) != 0 { t.Fatalf("unexpected errors: %s", errors) } checkMarks(t, true) errors = errors[0:0] // Test permission errors. Only possible if we're not root // and only on some file systems (AFS, FAT). To avoid errors during // all.bash on those file systems, skip during go test -short. if os.Getuid() > 0 && !testing.Short() { // introduce 2 errors: chmod top-level directories to 0 os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0) // 3) capture errors, expect two. // mark respective subtrees manually markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself tree.entries[1].mark-- tree.entries[3].mark-- err := markFn(fs.Walk(tree.name)) if err != nil { t.Fatalf("expected no error return from Walk, got %s", err) } if len(errors) != 2 { t.Errorf("expected 2 errors, got %d: %s", len(errors), errors) } // the inaccessible subtrees were marked manually checkMarks(t, true) errors = errors[0:0] // 4) capture errors, stop after first error. // mark respective subtrees manually markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself tree.entries[1].mark-- tree.entries[3].mark-- clear = false // error will stop processing err = markFn(fs.Walk(tree.name)) if err == nil { t.Fatalf("expected error return from Walk") } if len(errors) != 1 { t.Errorf("expected 1 error, got %d: %s", len(errors), errors) } // the inaccessible subtrees were marked manually checkMarks(t, false) errors = errors[0:0] // restore permissions os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770) } // cleanup if err := os.RemoveAll(tree.name); err != nil { t.Errorf("removeTree: %v", err) } }
// List finds all toolchains in the SRCLIBPATH. // // List does not find nested toolchains; i.e., if DIR is a toolchain // dir (with a DIR/Srclibtoolchain file), then none of DIR's // subdirectories are searched for toolchains. func List() ([]*Info, error) { if noToolchains { return nil, nil } var found []*Info seen := map[string]string{} dirs := strings.Split(srclib.Path, ":") // maps symlinked trees to their original path origDirs := map[string]string{} for i := 0; i < len(dirs); i++ { dir := dirs[i] if dir == "" { dir = "." } w := fs.Walk(dir) for w.Step() { if w.Err() != nil { return nil, w.Err() } fi := w.Stat() name := fi.Name() path := w.Path() if path != dir && (name[0] == '.' || name[0] == '_') { w.SkipDir() } else if fi.Mode()&os.ModeSymlink != 0 { // Check if symlink points to a directory. if sfi, err := os.Stat(path); err == nil { if !sfi.IsDir() { continue } } else if os.IsNotExist(err) { continue } else { return nil, err } // traverse symlinks but refer to symlinked trees' toolchains using // the path to them through the original entry in SRCLIBPATH dirs = append(dirs, path+"/") origDirs[path+"/"] = dir } else if fi.Mode().IsDir() { // Check for Srclibtoolchain file in this dir. if _, err := os.Stat(filepath.Join(path, ConfigFilename)); os.IsNotExist(err) { continue } else if err != nil { return nil, err } // Found a Srclibtoolchain file. path = filepath.Clean(path) var base string if orig, present := origDirs[dir]; present { base = orig } else { base = dir } toolchainPath, _ := filepath.Rel(base, path) if otherDir, seen := seen[toolchainPath]; seen { return nil, fmt.Errorf("saw 2 toolchains at path %s in dirs %s and %s", toolchainPath, otherDir, path) } seen[toolchainPath] = path info, err := newInfo(toolchainPath, path, ConfigFilename) if err != nil { return nil, err } found = append(found, info) // Disallow nested toolchains to speed up List. This // means that if DIR/Srclibtoolchain exists, no other // Srclibtoolchain files underneath DIR will be read. w.SkipDir() } } } return found, nil }