{"contents":"package git\n\nimport (\n\t\"io\"\n\t\"path\"\n\t\"strings\"\n\n\t\"github.com/go-git/go-git/v5/plumbing/filemode\"\n)\n\n// TreeEntry represents a file or directory in the repo tree.\ntype TreeEntry struct {\n\tName string `json:\"name\"`\n\tIsDir bool `json:\"isDir\"`\n\tIsFile bool `json:\"isFile\"`\n\tSize int64 `json:\"size,omitempty\"`\n\tMode string `json:\"mode\"`\n\tHash string `json:\"hash\"`\n\tIsLink bool `json:\"isLink,omitempty\"`\n\tTarget string `json:\"target,omitempty\"`\n}\n\n// Tree returns the entries in the tree at the given path.\nfunc (repo *Repo) Tree(treePath string) ([]TreeEntry, error) {\n\tcommit, err := repo.HeadCommit()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\ttree, err := commit.Tree()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif treePath != \"\" \u0026\u0026 treePath != \".\" {\n\t\ttree, err = tree.Tree(treePath)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tvar entries []TreeEntry\n\tfor _, e := range tree.Entries {\n\t\tentry := TreeEntry{\n\t\t\tName: e.Name,\n\t\t\tHash: e.Hash.String(),\n\t\t\tMode: e.Mode.String(),\n\t\t}\n\n\t\tswitch {\n\t\tcase e.Mode == filemode.Dir || e.Mode == filemode.Submodule:\n\t\t\tentry.IsDir = true\n\t\tcase e.Mode == filemode.Symlink:\n\t\t\tentry.IsFile = true\n\t\t\tentry.IsLink = true\n\t\t\t// Read symlink target\n\t\t\tblob, err := repo.r.BlobObject(e.Hash)\n\t\t\tif err == nil {\n\t\t\t\tr, err := blob.Reader()\n\t\t\t\tif err == nil {\n\t\t\t\t\tdata, _ := io.ReadAll(r)\n\t\t\t\t\tr.Close()\n\t\t\t\t\tentry.Target = string(data)\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\tentry.IsFile = true\n\t\t\tblob, err := repo.r.BlobObject(e.Hash)\n\t\t\tif err == nil {\n\t\t\t\tentry.Size = blob.Size\n\t\t\t}\n\t\t}\n\n\t\tentries = append(entries, entry)\n\t}\n\n\treturn entries, nil\n}\n\n// FileContent returns the content of a file at the given path.\nfunc (repo *Repo) FileContent(filePath string) (string, error) {\n\tcommit, err := repo.HeadCommit()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tfile, err := commit.File(filePath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn file.Contents()\n}\n\n// RawContent returns the raw bytes of a file.\nfunc (repo *Repo) RawContent(filePath string) ([]byte, error) {\n\tcommit, err := repo.HeadCommit()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfile, err := commit.File(filePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tr, err := file.Reader()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer r.Close()\n\n\treturn io.ReadAll(r)\n}\n\n// FileTree returns tree entries under a specific directory path.\nfunc (repo *Repo) FileTree(dirPath string) ([]TreeEntry, error) {\n\treturn repo.Tree(dirPath)\n}\n\n// FindReadme searches for a README file in the given tree path.\nfunc (repo *Repo) FindReadme(treePath string, readmeNames []string) (string, string, error) {\n\tentries, err := repo.Tree(treePath)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\n\tfor _, name := range readmeNames {\n\t\tfor _, e := range entries {\n\t\t\tif strings.EqualFold(e.Name, name) \u0026\u0026 e.IsFile {\n\t\t\t\tcontent, err := repo.FileContent(path.Join(treePath, e.Name))\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn e.Name, content, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"\", \"\", nil\n}\n","path":"git/tree.go","ref":"main"}