A vibe coded tangled fork which supports pijul.
at master 226 lines 5.2 kB view raw
1package vcs 2 3import ( 4 "context" 5 "io" 6 7 "tangled.org/core/knotserver/git" 8) 9 10// gitReadAdapter wraps a git.GitRepo to implement ReadRepo. 11type gitReadAdapter struct { 12 g *git.GitRepo 13} 14 15func newGitReadAdapter(g *git.GitRepo) *gitReadAdapter { 16 return &gitReadAdapter{g: g} 17} 18 19func (a *gitReadAdapter) VCSType() string { return "git" } 20func (a *gitReadAdapter) Path() string { return a.g.Path() } 21 22func (a *gitReadAdapter) History(offset, limit int) ([]HistoryEntry, error) { 23 commits, err := a.g.Commits(offset, limit) 24 if err != nil { 25 return nil, err 26 } 27 28 entries := make([]HistoryEntry, 0, len(commits)) 29 for _, c := range commits { 30 parents := make([]string, 0, len(c.ParentHashes)) 31 for _, p := range c.ParentHashes { 32 parents = append(parents, p.String()) 33 } 34 entries = append(entries, HistoryEntry{ 35 Hash: c.Hash.String(), 36 Author: Author{ 37 Name: c.Author.Name, 38 Email: c.Author.Email, 39 When: c.Author.When, 40 }, 41 Committer: Author{ 42 Name: c.Committer.Name, 43 Email: c.Committer.Email, 44 When: c.Committer.When, 45 }, 46 Message: c.Message, 47 Timestamp: c.Committer.When, 48 Parents: parents, 49 }) 50 } 51 return entries, nil 52} 53 54func (a *gitReadAdapter) TotalHistoryEntries() (int, error) { 55 return a.g.TotalCommits() 56} 57 58func (a *gitReadAdapter) HistoryEntry(hash string) (*HistoryEntry, error) { 59 c, err := a.g.Commit(gitHash(hash)) 60 if err != nil { 61 return nil, err 62 } 63 64 parents := make([]string, 0, len(c.ParentHashes)) 65 for _, p := range c.ParentHashes { 66 parents = append(parents, p.String()) 67 } 68 69 return &HistoryEntry{ 70 Hash: c.Hash.String(), 71 Author: Author{ 72 Name: c.Author.Name, 73 Email: c.Author.Email, 74 When: c.Author.When, 75 }, 76 Committer: Author{ 77 Name: c.Committer.Name, 78 Email: c.Committer.Email, 79 When: c.Committer.When, 80 }, 81 Message: c.Message, 82 Timestamp: c.Committer.When, 83 Parents: parents, 84 }, nil 85} 86 87func (a *gitReadAdapter) Branches(opts *PaginationOpts) ([]BranchInfo, error) { 88 var gitOpts *git.BranchesOptions 89 if opts != nil { 90 gitOpts = &git.BranchesOptions{ 91 Limit: opts.Limit, 92 Offset: opts.Offset, 93 } 94 } 95 96 branches, err := a.g.Branches(gitOpts) 97 if err != nil { 98 return nil, err 99 } 100 101 infos := make([]BranchInfo, 0, len(branches)) 102 for _, b := range branches { 103 info := BranchInfo{ 104 Name: b.Name, 105 Hash: b.Hash, 106 IsDefault: b.IsDefault, 107 } 108 if b.Commit != nil { 109 info.LatestEntry = &HistoryEntry{ 110 Hash: b.Commit.Hash.String(), 111 Author: Author{ 112 Name: b.Commit.Author.Name, 113 Email: b.Commit.Author.Email, 114 When: b.Commit.Author.When, 115 }, 116 Committer: Author{ 117 Name: b.Commit.Committer.Name, 118 Email: b.Commit.Committer.Email, 119 When: b.Commit.Committer.When, 120 }, 121 Message: b.Commit.Message, 122 Timestamp: b.Commit.Committer.When, 123 } 124 } 125 infos = append(infos, info) 126 } 127 return infos, nil 128} 129 130func (a *gitReadAdapter) DefaultBranch() (string, error) { 131 return a.g.FindMainBranch() 132} 133 134func (a *gitReadAdapter) FileTree(ctx context.Context, path string) ([]TreeEntry, error) { 135 files, err := a.g.FileTree(ctx, path) 136 if err != nil { 137 return nil, err 138 } 139 140 entries := make([]TreeEntry, 0, len(files)) 141 for _, f := range files { 142 entry := TreeEntry{ 143 Name: f.Name, 144 Mode: f.Mode, 145 Size: f.Size, 146 } 147 if f.LastCommit != nil { 148 entry.LastCommit = &LastCommitInfo{ 149 Hash: f.LastCommit.Hash.String(), 150 Message: f.LastCommit.Message, 151 When: f.LastCommit.When, 152 } 153 } 154 entries = append(entries, entry) 155 } 156 return entries, nil 157} 158 159func (a *gitReadAdapter) FileContentN(path string, cap int64) ([]byte, error) { 160 return a.g.FileContentN(path, cap) 161} 162 163func (a *gitReadAdapter) RawContent(path string) ([]byte, error) { 164 return a.g.RawContent(path) 165} 166 167func (a *gitReadAdapter) WriteTar(w io.Writer, prefix string) error { 168 return a.g.WriteTar(w, prefix) 169} 170 171func (a *gitReadAdapter) Tags(opts *PaginationOpts) ([]TagInfo, error) { 172 var gitOpts *git.TagsOptions 173 if opts != nil { 174 gitOpts = &git.TagsOptions{ 175 Limit: opts.Limit, 176 Offset: opts.Offset, 177 } 178 } 179 180 tags, err := a.g.Tags(gitOpts) 181 if err != nil { 182 return nil, err 183 } 184 185 infos := make([]TagInfo, 0, len(tags)) 186 for _, t := range tags { 187 info := TagInfo{ 188 Name: t.Name, 189 Hash: t.Hash.String(), 190 Message: t.Message, 191 Target: t.Target.String(), 192 } 193 if t.Tagger.Name != "" { 194 info.Tagger = &Author{ 195 Name: t.Tagger.Name, 196 Email: t.Tagger.Email, 197 When: t.Tagger.When, 198 } 199 } 200 infos = append(infos, info) 201 } 202 return infos, nil 203} 204 205// gitMutableAdapter wraps a git.GitRepo to implement MutableRepo. 206type gitMutableAdapter struct { 207 *gitReadAdapter 208} 209 210func newGitMutableAdapter(g *git.GitRepo) *gitMutableAdapter { 211 return &gitMutableAdapter{gitReadAdapter: newGitReadAdapter(g)} 212} 213 214func (a *gitMutableAdapter) SetDefaultBranch(name string) error { 215 return a.g.SetDefaultBranch(name) 216} 217 218func (a *gitMutableAdapter) DeleteBranch(name string) error { 219 return a.g.DeleteBranch(name) 220} 221 222// Git returns the underlying *git.GitRepo for git-specific operations 223// (diff, merge, format-patch, etc.) that don't belong in the VCS interface. 224func (a *gitReadAdapter) Git() *git.GitRepo { 225 return a.g 226}