| @@ -760,6 +760,8 @@ dashboard.delete_inactivate_accounts = Delete all inactive accounts | |||||
| dashboard.delete_inactivate_accounts_success = All inactivate accounts have been deleted successfully. | dashboard.delete_inactivate_accounts_success = All inactivate accounts have been deleted successfully. | ||||
| dashboard.delete_repo_archives = Delete all repositories archives | dashboard.delete_repo_archives = Delete all repositories archives | ||||
| dashboard.delete_repo_archives_success = All repositories archives have been deleted successfully. | dashboard.delete_repo_archives_success = All repositories archives have been deleted successfully. | ||||
| dashboard.delete_missing_repos = Delete all repository records that lost Git files | |||||
| dashboard.delete_missing_repos_success = All repository records that lost Git files have been deleted successfully. | |||||
| dashboard.git_gc_repos = Do garbage collection on repositories | dashboard.git_gc_repos = Do garbage collection on repositories | ||||
| dashboard.git_gc_repos_success = All repositories have done garbage collection successfully. | dashboard.git_gc_repos_success = All repositories have done garbage collection successfully. | ||||
| dashboard.resync_all_sshkeys = Rewrite '.ssh/authorized_keys' file (caution: non-Gogs keys will be lost) | dashboard.resync_all_sshkeys = Rewrite '.ssh/authorized_keys' file (caution: non-Gogs keys will be lost) | ||||
| @@ -1325,6 +1325,42 @@ func DeleteRepositoryArchives() error { | |||||
| }) | }) | ||||
| } | } | ||||
| // DeleteMissingRepositories deletes all repository records that lost Git files. | |||||
| func DeleteMissingRepositories() error { | |||||
| repos := make([]*Repository, 0, 5) | |||||
| if err := x.Where("id > 0").Iterate(new(Repository), | |||||
| func(idx int, bean interface{}) error { | |||||
| repo := bean.(*Repository) | |||||
| repoPath, err := repo.RepoPath() | |||||
| if err != nil { | |||||
| return fmt.Errorf("RepoPath [%d]: %v", repo.ID, err) | |||||
| } | |||||
| if !com.IsDir(repoPath) { | |||||
| repos = append(repos, repo) | |||||
| } | |||||
| return nil | |||||
| }); err != nil { | |||||
| if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteMissingRepositories: %v", err)); err2 != nil { | |||||
| log.Error(4, "CreateRepositoryNotice: %v", err2) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| if len(repos) == 0 { | |||||
| return nil | |||||
| } | |||||
| for _, repo := range repos { | |||||
| if err := DeleteRepository(repo.OwnerID, repo.ID); err != nil { | |||||
| if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepository [%d]: %v", repo.ID, err)); err2 != nil { | |||||
| log.Error(4, "CreateRepositoryNotice: %v", err2) | |||||
| } | |||||
| } | |||||
| } | |||||
| return nil | |||||
| } | |||||
| // RewriteRepositoryUpdateHook rewrites all repositories' update hook. | // RewriteRepositoryUpdateHook rewrites all repositories' update hook. | ||||
| func RewriteRepositoryUpdateHook() error { | func RewriteRepositoryUpdateHook() error { | ||||
| return x.Where("id > 0").Iterate(new(Repository), | return x.Where("id > 0").Iterate(new(Repository), | ||||
| @@ -116,6 +116,7 @@ type AdminOperation int | |||||
| const ( | const ( | ||||
| CLEAN_INACTIVATE_USER AdminOperation = iota + 1 | CLEAN_INACTIVATE_USER AdminOperation = iota + 1 | ||||
| CLEAN_REPO_ARCHIVES | CLEAN_REPO_ARCHIVES | ||||
| CLEAN_MISSING_REPOS | |||||
| GIT_GC_REPOS | GIT_GC_REPOS | ||||
| SYNC_SSH_AUTHORIZED_KEY | SYNC_SSH_AUTHORIZED_KEY | ||||
| SYNC_REPOSITORY_UPDATE_HOOK | SYNC_REPOSITORY_UPDATE_HOOK | ||||
| @@ -139,6 +140,9 @@ func Dashboard(ctx *middleware.Context) { | |||||
| case CLEAN_REPO_ARCHIVES: | case CLEAN_REPO_ARCHIVES: | ||||
| success = ctx.Tr("admin.dashboard.delete_repo_archives_success") | success = ctx.Tr("admin.dashboard.delete_repo_archives_success") | ||||
| err = models.DeleteRepositoryArchives() | err = models.DeleteRepositoryArchives() | ||||
| case CLEAN_MISSING_REPOS: | |||||
| success = ctx.Tr("admin.dashboard.delete_missing_repos_success") | |||||
| err = models.DeleteMissingRepositories() | |||||
| case GIT_GC_REPOS: | case GIT_GC_REPOS: | ||||
| success = ctx.Tr("admin.dashboard.git_gc_repos_success") | success = ctx.Tr("admin.dashboard.git_gc_repos_success") | ||||
| err = models.GitGcRepos() | err = models.GitGcRepos() | ||||
| @@ -28,17 +28,21 @@ | |||||
| <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=2">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=2">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | ||||
| </tr> | </tr> | ||||
| <tr> | <tr> | ||||
| <td>{{.i18n.Tr "admin.dashboard.git_gc_repos"}}</td> | |||||
| <td>{{.i18n.Tr "admin.dashboard.delete_missing_repos"}}</td> | |||||
| <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=3">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=3">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | ||||
| </tr> | </tr> | ||||
| <tr> | <tr> | ||||
| <td>{{.i18n.Tr "admin.dashboard.resync_all_sshkeys"}}</td> | |||||
| <td>{{.i18n.Tr "admin.dashboard.git_gc_repos"}}</td> | |||||
| <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=4">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=4">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | ||||
| </tr> | </tr> | ||||
| <tr> | <tr> | ||||
| <td>{{.i18n.Tr "admin.dashboard.resync_all_update_hooks"}}</td> | |||||
| <td>{{.i18n.Tr "admin.dashboard.resync_all_sshkeys"}}</td> | |||||
| <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=5">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=5">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | ||||
| </tr> | </tr> | ||||
| <tr> | |||||
| <td>{{.i18n.Tr "admin.dashboard.resync_all_update_hooks"}}</td> | |||||
| <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=6">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | |||||
| </tr> | |||||
| </tbody> | </tbody> | ||||
| </table> | </table> | ||||
| </div> | </div> | ||||