5
5
package models
6
6
7
7
import (
8
- "fmt"
9
- "net/url"
10
- "os"
11
8
"path/filepath"
12
9
"strings"
13
10
14
- "code.gitea.io/gitea/modules/git"
15
- "code.gitea.io/gitea/modules/log"
16
- "code.gitea.io/gitea/modules/sync"
17
-
18
11
"github.com/unknwon/com"
19
12
)
20
13
21
- var (
22
- reservedWikiNames = []string {"_pages" , "_new" , "_edit" , "raw" }
23
- wikiWorkingPool = sync .NewExclusivePool ()
24
- )
25
-
26
- // NormalizeWikiName normalizes a wiki name
27
- func NormalizeWikiName (name string ) string {
28
- return strings .Replace (name , "-" , " " , - 1 )
29
- }
30
-
31
- // WikiNameToSubURL converts a wiki name to its corresponding sub-URL.
32
- func WikiNameToSubURL (name string ) string {
33
- return url .QueryEscape (strings .Replace (name , " " , "-" , - 1 ))
34
- }
35
-
36
- // WikiNameToFilename converts a wiki name to its corresponding filename.
37
- func WikiNameToFilename (name string ) string {
38
- name = strings .Replace (name , " " , "-" , - 1 )
39
- return url .QueryEscape (name ) + ".md"
40
- }
41
-
42
- // WikiFilenameToName converts a wiki filename to its corresponding page name.
43
- func WikiFilenameToName (filename string ) (string , error ) {
44
- if ! strings .HasSuffix (filename , ".md" ) {
45
- return "" , ErrWikiInvalidFileName {filename }
46
- }
47
- basename := filename [:len (filename )- 3 ]
48
- unescaped , err := url .QueryUnescape (basename )
49
- if err != nil {
50
- return "" , err
51
- }
52
- return NormalizeWikiName (unescaped ), nil
53
- }
54
-
55
14
// WikiCloneLink returns clone URLs of repository wiki.
56
15
func (repo * Repository ) WikiCloneLink () * CloneLink {
57
16
return repo .cloneLink (x , true )
@@ -71,275 +30,3 @@ func (repo *Repository) WikiPath() string {
71
30
func (repo * Repository ) HasWiki () bool {
72
31
return com .IsDir (repo .WikiPath ())
73
32
}
74
-
75
- // InitWiki initializes a wiki for repository,
76
- // it does nothing when repository already has wiki.
77
- func (repo * Repository ) InitWiki () error {
78
- if repo .HasWiki () {
79
- return nil
80
- }
81
-
82
- if err := git .InitRepository (repo .WikiPath (), true ); err != nil {
83
- return fmt .Errorf ("InitRepository: %v" , err )
84
- } else if err = createDelegateHooks (repo .WikiPath ()); err != nil {
85
- return fmt .Errorf ("createDelegateHooks: %v" , err )
86
- }
87
- return nil
88
- }
89
-
90
- // nameAllowed checks if a wiki name is allowed
91
- func nameAllowed (name string ) error {
92
- for _ , reservedName := range reservedWikiNames {
93
- if name == reservedName {
94
- return ErrWikiReservedName {name }
95
- }
96
- }
97
- return nil
98
- }
99
-
100
- // updateWikiPage adds a new page to the repository wiki.
101
- func (repo * Repository ) updateWikiPage (doer * User , oldWikiName , newWikiName , content , message string , isNew bool ) (err error ) {
102
- if err = nameAllowed (newWikiName ); err != nil {
103
- return err
104
- }
105
- wikiWorkingPool .CheckIn (com .ToStr (repo .ID ))
106
- defer wikiWorkingPool .CheckOut (com .ToStr (repo .ID ))
107
-
108
- if err = repo .InitWiki (); err != nil {
109
- return fmt .Errorf ("InitWiki: %v" , err )
110
- }
111
-
112
- hasMasterBranch := git .IsBranchExist (repo .WikiPath (), "master" )
113
-
114
- basePath , err := CreateTemporaryPath ("update-wiki" )
115
- if err != nil {
116
- return err
117
- }
118
- defer func () {
119
- if err := RemoveTemporaryPath (basePath ); err != nil {
120
- log .Error ("Merge: RemoveTemporaryPath: %s" , err )
121
- }
122
- }()
123
-
124
- cloneOpts := git.CloneRepoOptions {
125
- Bare : true ,
126
- Shared : true ,
127
- }
128
-
129
- if hasMasterBranch {
130
- cloneOpts .Branch = "master"
131
- }
132
-
133
- if err := git .Clone (repo .WikiPath (), basePath , cloneOpts ); err != nil {
134
- log .Error ("Failed to clone repository: %s (%v)" , repo .FullName (), err )
135
- return fmt .Errorf ("Failed to clone repository: %s (%v)" , repo .FullName (), err )
136
- }
137
-
138
- gitRepo , err := git .OpenRepository (basePath )
139
- if err != nil {
140
- log .Error ("Unable to open temporary repository: %s (%v)" , basePath , err )
141
- return fmt .Errorf ("Failed to open new temporary repository in: %s %v" , basePath , err )
142
- }
143
- defer gitRepo .Close ()
144
-
145
- if hasMasterBranch {
146
- if err := gitRepo .ReadTreeToIndex ("HEAD" ); err != nil {
147
- log .Error ("Unable to read HEAD tree to index in: %s %v" , basePath , err )
148
- return fmt .Errorf ("Unable to read HEAD tree to index in: %s %v" , basePath , err )
149
- }
150
- }
151
-
152
- newWikiPath := WikiNameToFilename (newWikiName )
153
- if isNew {
154
- filesInIndex , err := gitRepo .LsFiles (newWikiPath )
155
- if err != nil {
156
- log .Error ("%v" , err )
157
- return err
158
- }
159
- for _ , file := range filesInIndex {
160
- if file == newWikiPath {
161
- return ErrWikiAlreadyExist {newWikiPath }
162
- }
163
- }
164
- } else {
165
- oldWikiPath := WikiNameToFilename (oldWikiName )
166
- filesInIndex , err := gitRepo .LsFiles (oldWikiPath )
167
- if err != nil {
168
- log .Error ("%v" , err )
169
- return err
170
- }
171
- found := false
172
- for _ , file := range filesInIndex {
173
- if file == oldWikiPath {
174
- found = true
175
- break
176
- }
177
- }
178
- if found {
179
- err := gitRepo .RemoveFilesFromIndex (oldWikiPath )
180
- if err != nil {
181
- log .Error ("%v" , err )
182
- return err
183
- }
184
- }
185
- }
186
-
187
- // FIXME: The wiki doesn't have lfs support at present - if this changes need to check attributes here
188
-
189
- objectHash , err := gitRepo .HashObject (strings .NewReader (content ))
190
- if err != nil {
191
- log .Error ("%v" , err )
192
- return err
193
- }
194
-
195
- if err := gitRepo .AddObjectToIndex ("100644" , objectHash , newWikiPath ); err != nil {
196
- log .Error ("%v" , err )
197
- return err
198
- }
199
-
200
- tree , err := gitRepo .WriteTree ()
201
- if err != nil {
202
- log .Error ("%v" , err )
203
- return err
204
- }
205
-
206
- commitTreeOpts := git.CommitTreeOpts {
207
- Message : message ,
208
- }
209
-
210
- sign , signingKey := repo .SignWikiCommit (doer )
211
- if sign {
212
- commitTreeOpts .KeyID = signingKey
213
- } else {
214
- commitTreeOpts .NoGPGSign = true
215
- }
216
- if hasMasterBranch {
217
- commitTreeOpts .Parents = []string {"HEAD" }
218
- }
219
- commitHash , err := gitRepo .CommitTree (doer .NewGitSig (), tree , commitTreeOpts )
220
- if err != nil {
221
- log .Error ("%v" , err )
222
- return err
223
- }
224
-
225
- if err := git .Push (basePath , git.PushOptions {
226
- Remote : "origin" ,
227
- Branch : fmt .Sprintf ("%s:%s%s" , commitHash .String (), git .BranchPrefix , "master" ),
228
- Env : FullPushingEnvironment (
229
- doer ,
230
- doer ,
231
- repo ,
232
- repo .Name + ".wiki" ,
233
- 0 ,
234
- ),
235
- }); err != nil {
236
- log .Error ("%v" , err )
237
- return fmt .Errorf ("Push: %v" , err )
238
- }
239
-
240
- return nil
241
- }
242
-
243
- // AddWikiPage adds a new wiki page with a given wikiPath.
244
- func (repo * Repository ) AddWikiPage (doer * User , wikiName , content , message string ) error {
245
- return repo .updateWikiPage (doer , "" , wikiName , content , message , true )
246
- }
247
-
248
- // EditWikiPage updates a wiki page identified by its wikiPath,
249
- // optionally also changing wikiPath.
250
- func (repo * Repository ) EditWikiPage (doer * User , oldWikiName , newWikiName , content , message string ) error {
251
- return repo .updateWikiPage (doer , oldWikiName , newWikiName , content , message , false )
252
- }
253
-
254
- // DeleteWikiPage deletes a wiki page identified by its path.
255
- func (repo * Repository ) DeleteWikiPage (doer * User , wikiName string ) (err error ) {
256
- wikiWorkingPool .CheckIn (com .ToStr (repo .ID ))
257
- defer wikiWorkingPool .CheckOut (com .ToStr (repo .ID ))
258
-
259
- if err = repo .InitWiki (); err != nil {
260
- return fmt .Errorf ("InitWiki: %v" , err )
261
- }
262
-
263
- basePath , err := CreateTemporaryPath ("update-wiki" )
264
- if err != nil {
265
- return err
266
- }
267
- defer func () {
268
- if err := RemoveTemporaryPath (basePath ); err != nil {
269
- log .Error ("Merge: RemoveTemporaryPath: %s" , err )
270
- }
271
- }()
272
-
273
- if err := git .Clone (repo .WikiPath (), basePath , git.CloneRepoOptions {
274
- Bare : true ,
275
- Shared : true ,
276
- Branch : "master" ,
277
- }); err != nil {
278
- log .Error ("Failed to clone repository: %s (%v)" , repo .FullName (), err )
279
- return fmt .Errorf ("Failed to clone repository: %s (%v)" , repo .FullName (), err )
280
- }
281
-
282
- gitRepo , err := git .OpenRepository (basePath )
283
- if err != nil {
284
- log .Error ("Unable to open temporary repository: %s (%v)" , basePath , err )
285
- return fmt .Errorf ("Failed to open new temporary repository in: %s %v" , basePath , err )
286
- }
287
- defer gitRepo .Close ()
288
-
289
- if err := gitRepo .ReadTreeToIndex ("HEAD" ); err != nil {
290
- log .Error ("Unable to read HEAD tree to index in: %s %v" , basePath , err )
291
- return fmt .Errorf ("Unable to read HEAD tree to index in: %s %v" , basePath , err )
292
- }
293
-
294
- wikiPath := WikiNameToFilename (wikiName )
295
- filesInIndex , err := gitRepo .LsFiles (wikiPath )
296
- found := false
297
- for _ , file := range filesInIndex {
298
- if file == wikiPath {
299
- found = true
300
- break
301
- }
302
- }
303
- if found {
304
- err := gitRepo .RemoveFilesFromIndex (wikiPath )
305
- if err != nil {
306
- return err
307
- }
308
- } else {
309
- return os .ErrNotExist
310
- }
311
-
312
- // FIXME: The wiki doesn't have lfs support at present - if this changes need to check attributes here
313
-
314
- tree , err := gitRepo .WriteTree ()
315
- if err != nil {
316
- return err
317
- }
318
- message := "Delete page '" + wikiName + "'"
319
- commitTreeOpts := git.CommitTreeOpts {
320
- Message : message ,
321
- Parents : []string {"HEAD" },
322
- }
323
-
324
- sign , signingKey := repo .SignWikiCommit (doer )
325
- if sign {
326
- commitTreeOpts .KeyID = signingKey
327
- } else {
328
- commitTreeOpts .NoGPGSign = true
329
- }
330
-
331
- commitHash , err := gitRepo .CommitTree (doer .NewGitSig (), tree , commitTreeOpts )
332
- if err != nil {
333
- return err
334
- }
335
-
336
- if err := git .Push (basePath , git.PushOptions {
337
- Remote : "origin" ,
338
- Branch : fmt .Sprintf ("%s:%s%s" , commitHash .String (), git .BranchPrefix , "master" ),
339
- Env : PushingEnvironment (doer , repo ),
340
- }); err != nil {
341
- return fmt .Errorf ("Push: %v" , err )
342
- }
343
-
344
- return nil
345
- }
0 commit comments