From bfcce5f86ccd46d18b6ca53889b04cc3b13fd2d8 Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Sat, 14 Dec 2019 11:30:39 +0800
Subject: [PATCH] Remove release attachments which repository has been deleted
 (#9334)

---
 models/migrations/migrations.go |  2 ++
 models/migrations/v112.go       | 41 +++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 models/migrations/v112.go

diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 8aa39904f3..78fbc18ca5 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -278,6 +278,8 @@ var migrations = []Migration{
 	NewMigration("change review content type to text", changeReviewContentToText),
 	// v111 -> v112
 	NewMigration("update branch protection for can push and whitelist enable", addBranchProtectionCanPushAndEnableWhitelist),
+	// v112 -> v113
+	NewMigration("remove release attachments which repository deleted", removeAttachmentMissedRepo),
 }
 
 // Migrate database to current version
diff --git a/models/migrations/v112.go b/models/migrations/v112.go
new file mode 100644
index 0000000000..c1087b0c47
--- /dev/null
+++ b/models/migrations/v112.go
@@ -0,0 +1,41 @@
+// 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"
+	"xorm.io/builder"
+	"xorm.io/xorm"
+)
+
+func removeAttachmentMissedRepo(x *xorm.Engine) error {
+	type Attachment struct {
+		UUID string `xorm:"uuid"`
+	}
+	var start int
+	attachments := make([]*Attachment, 0, 50)
+	for {
+		err := x.Select("uuid").Where(builder.NotIn("release_id", builder.Select("id").From("`release`"))).
+			OrderBy("id").Limit(50, start).Find(&attachments)
+		if err != nil {
+			return err
+		}
+
+		for i := 0; i < len(attachments); i++ {
+			os.RemoveAll(models.AttachmentLocalPath(attachments[i].UUID))
+		}
+
+		if len(attachments) < 50 {
+			break
+		}
+		start += 50
+		attachments = attachments[:0]
+	}
+
+	_, err := x.Exec("DELETE FROM attachment WHERE release_id NOT IN (SELECT id FROM `release`)")
+	return err
+}