1package git
2
3import (
4 "path/filepath"
5
6 "github.com/gogs/git-module"
7)
8
9var (
10 DiffMaxFiles = 1000
11 DiffMaxFileLines = 1000
12 DiffMaxLineChars = 1000
13)
14
15// Repository is a wrapper around git.Repository with helper methods.
16type Repository struct {
17 *git.Repository
18 Path string
19}
20
21// Clone clones a repository.
22func Clone(src, dst string, opts ...git.CloneOptions) error {
23 return git.Clone(src, dst, opts...)
24}
25
26// Init initializes and opens a new git repository.
27func Init(path string, bare bool) (*Repository, error) {
28 err := git.Init(path, git.InitOptions{Bare: bare})
29 if err != nil {
30 return nil, err
31 }
32 return Open(path)
33}
34
35// Open opens a git repository at the given path.
36func Open(path string) (*Repository, error) {
37 repo, err := git.Open(path)
38 if err != nil {
39 return nil, err
40 }
41 return &Repository{
42 Repository: repo,
43 Path: path,
44 }, nil
45}
46
47// Name returns the name of the repository.
48func (r *Repository) Name() string {
49 return filepath.Base(r.Path)
50}
51
52// HEAD returns the HEAD reference for a repository.
53func (r *Repository) HEAD() (*Reference, error) {
54 rn, err := r.SymbolicRef()
55 if err != nil {
56 return nil, err
57 }
58 hash, err := r.ShowRefVerify(rn)
59 if err != nil {
60 return nil, err
61 }
62 return &Reference{
63 Reference: &git.Reference{
64 ID: hash,
65 Refspec: rn,
66 },
67 Hash: Hash(hash),
68 path: r.Path,
69 }, nil
70}
71
72// References returns the references for a repository.
73func (r *Repository) References() ([]*Reference, error) {
74 refs, err := r.ShowRef()
75 if err != nil {
76 return nil, err
77 }
78 rrefs := make([]*Reference, 0, len(refs))
79 for _, ref := range refs {
80 rrefs = append(rrefs, &Reference{
81 Reference: ref,
82 Hash: Hash(ref.ID),
83 path: r.Path,
84 })
85 }
86 return rrefs, nil
87}
88
89// Tree returns the tree for the given reference.
90func (r *Repository) Tree(ref *Reference) (*Tree, error) {
91 if ref == nil {
92 rref, err := r.HEAD()
93 if err != nil {
94 return nil, err
95 }
96 ref = rref
97 }
98 tree, err := r.LsTree(ref.Hash.String())
99 if err != nil {
100 return nil, err
101 }
102 return &Tree{
103 Tree: tree,
104 Path: "",
105 }, nil
106}
107
108// TreePath returns the tree for the given path.
109func (r *Repository) TreePath(ref *Reference, path string) (*Tree, error) {
110 path = filepath.Clean(path)
111 if path == "." {
112 path = ""
113 }
114 if path == "" {
115 return r.Tree(ref)
116 }
117 t, err := r.Tree(ref)
118 if err != nil {
119 return nil, err
120 }
121 return t.SubTree(path)
122}
123
124// Diff returns the diff for the given commit.
125func (r *Repository) Diff(commit *Commit) (*Diff, error) {
126 ddiff, err := r.Repository.Diff(commit.Hash.String(), DiffMaxFiles, DiffMaxFileLines, DiffMaxLineChars)
127 if err != nil {
128 return nil, err
129 }
130 files := make([]*DiffFile, 0, len(ddiff.Files))
131 for _, df := range ddiff.Files {
132 sections := make([]*DiffSection, 0, len(df.Sections))
133 for _, ds := range df.Sections {
134 sections = append(sections, &DiffSection{
135 DiffSection: ds,
136 })
137 }
138 files = append(files, &DiffFile{
139 DiffFile: df,
140 Sections: sections,
141 })
142 }
143 diff := &Diff{
144 Diff: ddiff,
145 Files: files,
146 }
147 return diff, nil
148}
149
150// Patch returns the patch for the given reference.
151func (r *Repository) Patch(commit *Commit) (string, error) {
152 diff, err := r.Diff(commit)
153 if err != nil {
154 return "", err
155 }
156 return diff.Patch(), err
157}
158
159// CountCommits returns the number of commits in the repository.
160func (r *Repository) CountCommits(ref *Reference) (int64, error) {
161 return r.Repository.RevListCount([]string{ref.Name().String()})
162}
163
164// CommitsByPage returns the commits for a given page and size.
165func (r *Repository) CommitsByPage(ref *Reference, page, size int) (Commits, error) {
166 cs, err := r.Repository.CommitsByPage(ref.Name().String(), page, size)
167 if err != nil {
168 return nil, err
169 }
170 commits := make(Commits, len(cs))
171 for i, c := range cs {
172 commits[i] = &Commit{
173 Commit: c,
174 Hash: Hash(c.ID.String()),
175 }
176 }
177 return commits, nil
178}
179
180// UpdateServerInfo updates the repository server info.
181func (r *Repository) UpdateServerInfo() error {
182 cmd := git.NewCommand("update-server-info")
183 _, err := cmd.RunInDir(r.Path)
184 return err
185}