diff --git a/.gitignore b/.gitignore index eab92b4..ec0ffe9 100644 --- a/.gitignore +++ b/.gitignore @@ -82,11 +82,11 @@ cpu.out /yarn.lock /yarn-error.log /npm-debug.log* -/public/js -/public/serviceworker.js -/public/css -/public/fonts -/public/img/webpack +# /public/js +# /public/serviceworker.js +# /public/css +# /public/fonts +# /public/img/webpack /vendor /web_src/fomantic/node_modules /web_src/fomantic/build/* diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go new file mode 100644 index 0000000..ee328b5 --- /dev/null +++ b/modules/git/repo_commit.go @@ -0,0 +1,33 @@ +package git + +import ( + "bytes" + + gitea_git "code.gitea.io/gitea/modules/git" +) + +const prettyLogFormat = `--pretty=format:%H` + +func GetFirstAndLastCommitByPath(repo *gitea_git.Repository, revision, relpath string) (*gitea_git.Commit, *gitea_git.Commit, error) { + stdout, _, runErr := gitea_git.NewCommand(repo.Ctx, "log", revision, prettyLogFormat, "--", relpath).RunStdBytes(&gitea_git.RunOpts{Dir: repo.Path}) + if runErr != nil { + return nil, nil, runErr + } + + var commits []*gitea_git.Commit + if len(stdout) == 0 { + return nil, nil, nil + } + + parts := bytes.Split(stdout, []byte{'\n'}) + + for _, commitID := range parts { + commit, err := repo.GetCommit(string(commitID)) + if err != nil { + return nil, nil, err + } + commits = append(commits, commit) + } + + return commits[0], commits[len(commits)-1], nil +} diff --git a/modules/structs/wiki.go b/modules/structs/wiki.go new file mode 100644 index 0000000..a555c1d --- /dev/null +++ b/modules/structs/wiki.go @@ -0,0 +1,44 @@ +package structs + +type WikiesResponse struct { + WikiMeta + WikiCloneLink CloneLink `json:"wiki_clone_link"` +} + +type WikiMeta struct { + Name string `json:"name"` + Commit WikiCommit `json:"commit"` + FirstCommit WikiCommit `json:"-"` + //WikiCloneLink CloneLink `json:"wiki_clone_link"` +} + +type WikiCommit struct { + ID string `json:"id"` + Message string `json:"message"` + Author WikiUser `json:"author"` + Commiter WikiUser `json:"-"` +} + +type WikiUser struct { + Name string `json:"name"` + Email string `json:"email"` + When int64 `json:"when"` +} + +type WikiResponse struct { + WikiMeta + CommitCounts int64 `json:"commit_counts"` + MdContent string `json:"md_content"` + SimpleContent string `json:"simple_content"` + WikiCloneLink CloneLink `json:"wiki_clone_link"` +} + +type WikiOption struct { + Name string `json:"name"` + Content string `json:"content"` + CommitMessage string `json:"commit_message"` +} +type CloneLink struct { + SSH string `json:"ssh"` + HTTPS string `json:"https"` +} diff --git a/routers/hat/hat.go b/routers/hat/hat.go index cd0b2f5..50703e9 100644 --- a/routers/hat/hat.go +++ b/routers/hat/hat.go @@ -53,6 +53,9 @@ func Routers() *web.Route { m.Get("/branch_name_set", context.ReferencesGitRepo(), repo.BranchNameSet) m.Get("/tag_name_set", context.ReferencesGitRepo(), repo.TagNameSet) + m.Group("/wikies", func() { + m.Combo("").Get(repo.ListWikiPages) + }) }, repoAssignment()) }) }) diff --git a/routers/hat/repo/wiki.go b/routers/hat/repo/wiki.go new file mode 100644 index 0000000..abcfaf8 --- /dev/null +++ b/routers/hat/repo/wiki.go @@ -0,0 +1,114 @@ +package repo + +import ( + "net/http" + "sort" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" + wiki_service "code.gitea.io/gitea/services/wiki" + hat_git "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/git" + hat_api "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/structs" +) + +func ListWikiPages(ctx *context.APIContext) { + if !ctx.Repo.Repository.HasWiki() { + return + } + + wikiCloneWiki := ctx.Repo.Repository.WikiCloneLink() + wikiRepo, commit, err := findWikiRepoCommit(ctx.Context) + defer func() { + if wikiRepo != nil { + wikiRepo.Close() + } + }() + if err != nil { + ctx.ServerError("findWikiRepoCommit", err) + return + } + + entries, err := commit.ListEntries() + if err != nil { + ctx.ServerError("ListEntries", err) + return + } + + pages := make([]hat_api.WikiesResponse, 0, len(entries)) + for _, entry := range entries { + if !entry.IsRegular() { + continue + } + lastCommit, firstCommit, err := hat_git.GetFirstAndLastCommitByPath(wikiRepo, "master", entry.Name()) + if err != nil { + ctx.ServerError("GetCommitByPath", err) + return + } + wikiName, err := wiki_service.FilenameToName(entry.Name()) + if err != nil { + if models.IsErrWikiInvalidFileName(err) { + continue + } + ctx.ServerError("wiki_service.FilenameToName", err) + return + } + pages = append(pages, hat_api.WikiesResponse{ + WikiCloneLink: hat_api.CloneLink{ + HTTPS: wikiCloneWiki.HTTPS, + SSH: wikiCloneWiki.SSH, + }, + WikiMeta: hat_api.WikiMeta{ + Name: wikiName, + Commit: hat_api.WikiCommit{ + Author: hat_api.WikiUser{ + Name: lastCommit.Author.Name, + Email: lastCommit.Author.Email, + When: lastCommit.Author.When.Unix(), + }, + Commiter: hat_api.WikiUser{ + Name: lastCommit.Committer.Name, + Email: lastCommit.Committer.Email, + When: lastCommit.Author.When.Unix(), + }, + ID: lastCommit.ID.String(), + Message: lastCommit.Message(), + }, + FirstCommit: hat_api.WikiCommit{ + Author: hat_api.WikiUser{ + Name: firstCommit.Author.Name, + Email: firstCommit.Author.Email, + When: firstCommit.Author.When.Unix(), + }, + Commiter: hat_api.WikiUser{ + Name: firstCommit.Committer.Name, + Email: firstCommit.Committer.Email, + When: firstCommit.Author.When.Unix(), + }, + ID: firstCommit.ID.String(), + Message: firstCommit.Message(), + }, + }, + }) + } + + sort.Slice(pages, func(i, j int) bool { + return pages[i].FirstCommit.Author.When > pages[j].FirstCommit.Author.When + }) + + ctx.JSON(http.StatusOK, pages) +} + +func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) { + wikiRepo, err := git.OpenRepository(ctx, ctx.Repo.Repository.WikiPath()) + if err != nil { + ctx.ServerError("OpenRepository", err) + return nil, nil, err + } + + commit, err := wikiRepo.GetBranchCommit("master") + if err != nil { + return wikiRepo, nil, err + } + return wikiRepo, commit, nil +}