code: func (h *stiGit) LsTree(repo, ref string, recursive bool) ([]os.FileInfo, error) {
  	args := []string{"ls-tree", ref}
  	if recursive {
  		args = append(args, "-r")
  	}
  
  	opts := cmd.CommandOpts{
  		Dir: repo,
  	}
  
  	r, err := h.StartWithStdoutPipe(opts, "git", args...)
  	if err != nil {
  		return nil, err
  	}
  
  	submodules := []string{}
  	rv := []os.FileInfo{}
  	scanner := bufio.NewScanner(r)
  	for scanner.Scan() {
  		text := scanner.Text()
  		m := lsTreeRegexp.FindStringSubmatch(text)
  		if m == nil {
  			return nil, fmt.Errorf("unparsable response %q from git ls-files", text)
  		}
  		mode, _ := strconv.ParseInt(m[1], 8, 0)
  		path := m[2]
  		if recursive && mode == 0160000 { // S_IFGITLINK
  			submodules = append(submodules, filepath.Join(repo, path))
  			continue
  		}
  		rv = append(rv, &fs.FileInfo{FileMode: os.FileMode(mode), FileName: path})
  	}
  	err = scanner.Err()
  	if err != nil {
  		h.Wait()
  		return nil, err
  	}
  
  	err = h.Wait()
  	if err != nil {
  		return nil, err
  	}
  
  	for _, submodule := range submodules {
  		rrv, err := h.LsTree(submodule, "HEAD", recursive)
  		if err != nil {
  			return nil, err
  		}
  		rv = append(rv, rrv...)
  	}
  
  	return rv, nil
  }
docs: // LsTree returns a slice of os.FileInfo objects populated with the paths and
  // file modes of files known to Git.  This is used on Windows systems where the
  // executable mode metadata is lost on git checkout.