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
- reservedUncycloNames = []string {"_pages" , "_new" , "_edit" , "raw" }
23
- wikiWorkingPool = sync .NewExclusivePool ()
24
- )
25
-
26
- // NormalizeUncycloName normalizes a wiki name
27
- func NormalizeUncycloName (name string ) string {
28
- return strings .Replace (name , "-" , " " , - 1 )
29
- }
30
-
31
- // UncycloNameToSubURL converts a wiki name to its corresponding sub-URL.
32
- func UncycloNameToSubURL (name string ) string {
33
- return url .QueryEscape (strings .Replace (name , " " , "-" , - 1 ))
34
- }
35
-
36
- // UncycloNameToFilename converts a wiki name to its corresponding filename.
37
- func UncycloNameToFilename (name string ) string {
38
- name = strings .Replace (name , " " , "-" , - 1 )
39
- return url .QueryEscape (name ) + ".md"
40
- }
41
-
42
- // UncycloFilenameToName converts a wiki filename to its corresponding page name.
43
- func UncycloFilenameToName (filename string ) (string , error ) {
44
- if ! strings .HasSuffix (filename , ".md" ) {
45
- return "" , ErrUncycloInvalidFileName {filename }
46
- }
47
- basename := filename [:len (filename )- 3 ]
48
- unescaped , err := url .QueryUnescape (basename )
49
- if err != nil {
50
- return "" , err
51
- }
52
- return NormalizeUncycloName (unescaped ), nil
53
- }
54
-
55
14
// UncycloCloneLink returns clone URLs of repository wiki.
56
15
func (repo * Repository ) UncycloCloneLink () * CloneLink {
57
16
return repo .cloneLink (x , true )
@@ -71,275 +30,3 @@ func (repo *Repository) UncycloPath() string {
71
30
func (repo * Repository ) HasUncyclo () bool {
72
31
return com .IsDir (repo .UncycloPath ())
73
32
}
74
-
75
- // InitUncyclo initializes a wiki for repository,
76
- // it does nothing when repository already has wiki.
77
- func (repo * Repository ) InitUncyclo () error {
78
- if repo .HasUncyclo () {
79
- return nil
80
- }
81
-
82
- if err := git .InitRepository (repo .UncycloPath (), true ); err != nil {
83
- return fmt .Errorf ("InitRepository: %v" , err )
84
- } else if err = createDelegateHooks (repo .UncycloPath ()); 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 reservedUncycloNames {
93
- if name == reservedName {
94
- return ErrUncycloReservedName {name }
95
- }
96
- }
97
- return nil
98
- }
99
-
100
- // updateUncycloPage adds a new page to the repository wiki.
101
- func (repo * Repository ) updateUncycloPage (doer * User , oldUncycloName , newUncycloName , content , message string , isNew bool ) (err error ) {
102
- if err = nameAllowed (newUncycloName ); 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 .InitUncyclo (); err != nil {
109
- return fmt .Errorf ("InitUncyclo: %v" , err )
110
- }
111
-
112
- hasMasterBranch := git .IsBranchExist (repo .UncycloPath (), "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 .UncycloPath (), 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
- newUncycloPath := UncycloNameToFilename (newUncycloName )
153
- if isNew {
154
- filesInIndex , err := gitRepo .LsFiles (newUncycloPath )
155
- if err != nil {
156
- log .Error ("%v" , err )
157
- return err
158
- }
159
- for _ , file := range filesInIndex {
160
- if file == newUncycloPath {
161
- return ErrUncycloAlreadyExist {newUncycloPath }
162
- }
163
- }
164
- } else {
165
- oldUncycloPath := UncycloNameToFilename (oldUncycloName )
166
- filesInIndex , err := gitRepo .LsFiles (oldUncycloPath )
167
- if err != nil {
168
- log .Error ("%v" , err )
169
- return err
170
- }
171
- found := false
172
- for _ , file := range filesInIndex {
173
- if file == oldUncycloPath {
174
- found = true
175
- break
176
- }
177
- }
178
- if found {
179
- err := gitRepo .RemoveFilesFromIndex (oldUncycloPath )
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 , newUncycloPath ); 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 .SignUncycloCommit (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
- // AddUncycloPage adds a new wiki page with a given wikiPath.
244
- func (repo * Repository ) AddUncycloPage (doer * User , wikiName , content , message string ) error {
245
- return repo .updateUncycloPage (doer , "" , wikiName , content , message , true )
246
- }
247
-
248
- // EditUncycloPage updates a wiki page identified by its wikiPath,
249
- // optionally also changing wikiPath.
250
- func (repo * Repository ) EditUncycloPage (doer * User , oldUncycloName , newUncycloName , content , message string ) error {
251
- return repo .updateUncycloPage (doer , oldUncycloName , newUncycloName , content , message , false )
252
- }
253
-
254
- // DeleteUncycloPage deletes a wiki page identified by its path.
255
- func (repo * Repository ) DeleteUncycloPage (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 .InitUncyclo (); err != nil {
260
- return fmt .Errorf ("InitUncyclo: %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 .UncycloPath (), 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 := UncycloNameToFilename (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 .SignUncycloCommit (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