Delete releases attachments if release is deleted (#6068)
* delete attachments from the database and file system * add migration * fix import statements * fix package name * remove conditional should in case the confi has been changed and the server restarted * simplify deletion of attachments in DB * fix CI build * fix review * add copyright in the proper place * fix review
This commit is contained in:
		
							parent
							
								
									6322d254e7
								
							
						
					
					
						commit
						63ff61615e
					
				
					 4 changed files with 63 additions and 1 deletions
				
			
		|  | @ -246,6 +246,8 @@ var migrations = []Migration{ | ||||||
| 	NewMigration("add enable_status_check, status_check_contexts to protected_branch", addStatusCheckColumnsForProtectedBranches), | 	NewMigration("add enable_status_check, status_check_contexts to protected_branch", addStatusCheckColumnsForProtectedBranches), | ||||||
| 	// v95 -> v96
 | 	// v95 -> v96
 | ||||||
| 	NewMigration("add table columns for cross referencing issues", addCrossReferenceColumns), | 	NewMigration("add table columns for cross referencing issues", addCrossReferenceColumns), | ||||||
|  | 	// v96 -> v97
 | ||||||
|  | 	NewMigration("delete orphaned attachments", deleteOrphanedAttachments), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Migrate database to current version
 | // Migrate database to current version
 | ||||||
|  |  | ||||||
|  | @ -14,5 +14,4 @@ func addIsLockedToIssues(x *xorm.Engine) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return x.Sync2(new(Issue)) | 	return x.Sync2(new(Issue)) | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										48
									
								
								models/migrations/v96.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								models/migrations/v96.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package migrations | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 
 | ||||||
|  | 	"code.gitea.io/gitea/models" | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
|  | 
 | ||||||
|  | 	"github.com/go-xorm/xorm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func deleteOrphanedAttachments(x *xorm.Engine) error { | ||||||
|  | 
 | ||||||
|  | 	type Attachment struct { | ||||||
|  | 		ID        int64  `xorm:"pk autoincr"` | ||||||
|  | 		UUID      string `xorm:"uuid UNIQUE"` | ||||||
|  | 		IssueID   int64  `xorm:"INDEX"` | ||||||
|  | 		ReleaseID int64  `xorm:"INDEX"` | ||||||
|  | 		CommentID int64 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sess := x.NewSession() | ||||||
|  | 	defer sess.Close() | ||||||
|  | 
 | ||||||
|  | 	err := sess.BufferSize(setting.Database.IterateBufferSize). | ||||||
|  | 		Where("`comment_id` = 0 and (`release_id` = 0 or `release_id` not in (select `id` from `release`))").Cols("uuid"). | ||||||
|  | 		Iterate(new(Attachment), | ||||||
|  | 			func(idx int, bean interface{}) error { | ||||||
|  | 				attachment := bean.(*Attachment) | ||||||
|  | 
 | ||||||
|  | 				if err := os.RemoveAll(models.AttachmentLocalPath(attachment.UUID)); err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				_, err := sess.ID(attachment.ID).NoAutoCondition().Delete(attachment) | ||||||
|  | 				return err | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sess.Commit() | ||||||
|  | } | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -6,6 +7,7 @@ package models | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"os" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
|  | @ -357,6 +359,17 @@ func DeleteReleaseByID(id int64, doer *User, delTag bool) error { | ||||||
| 		return fmt.Errorf("LoadAttributes: %v", err) | 		return fmt.Errorf("LoadAttributes: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if _, err := x.Delete(&Attachment{ReleaseID: id}); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for i := range rel.Attachments { | ||||||
|  | 		attachment := rel.Attachments[i] | ||||||
|  | 		if err := os.RemoveAll(attachment.LocalPath()); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	mode, _ := AccessLevel(doer, rel.Repo) | 	mode, _ := AccessLevel(doer, rel.Repo) | ||||||
| 	if err := PrepareWebhooks(rel.Repo, HookEventRelease, &api.ReleasePayload{ | 	if err := PrepareWebhooks(rel.Repo, HookEventRelease, &api.ReleasePayload{ | ||||||
| 		Action:     api.HookReleaseDeleted, | 		Action:     api.HookReleaseDeleted, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue