Repo size in admin panel (#1482)
* Implementation of the feature to view repository size in admin panel * Move GetRepoSize to git module * Repository.RepoSize -> Repository.Size * RepoSize -> Size in template * Redo a few bits and pieces * Update size when syncing mirror or forking * Remove GetRepoSize * Changed fatal errors to error message * Copy migration code from Gogs * make fmt
This commit is contained in:
parent
54f0293f0a
commit
be6edaddcb
|
@ -104,6 +104,8 @@ var migrations = []Migration{
|
||||||
NewMigration("generate and migrate repo and wiki Git hooks", generateAndMigrateGitHookChains),
|
NewMigration("generate and migrate repo and wiki Git hooks", generateAndMigrateGitHookChains),
|
||||||
// v27 -> v28
|
// v27 -> v28
|
||||||
NewMigration("change mirror interval from hours to time.Duration", convertIntervalToDuration),
|
NewMigration("change mirror interval from hours to time.Duration", convertIntervalToDuration),
|
||||||
|
// v28 -> v29
|
||||||
|
NewMigration("add field for repo size", addRepoSize),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate database to current version
|
// Migrate database to current version
|
||||||
|
|
77
models/migrations/v28.go
Normal file
77
models/migrations/v28.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2017 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2017 Gitea. 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 (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/git"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addRepoSize(x *xorm.Engine) (err error) {
|
||||||
|
log.Info("This migration could take up to minutes, please be patient.")
|
||||||
|
type Repository struct {
|
||||||
|
ID int64
|
||||||
|
OwnerID int64
|
||||||
|
Name string
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
type User struct {
|
||||||
|
ID int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
if err = x.Sync2(new(Repository)); err != nil {
|
||||||
|
return fmt.Errorf("Sync2: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the sake of SQLite3, we can't use x.Iterate here.
|
||||||
|
offset := 0
|
||||||
|
for {
|
||||||
|
repos := make([]*Repository, 0, 10)
|
||||||
|
if err = x.Sql(fmt.Sprintf("SELECT * FROM `repository` ORDER BY id ASC LIMIT 10 OFFSET %d", offset)).
|
||||||
|
Find(&repos); err != nil {
|
||||||
|
return fmt.Errorf("select repos [offset: %d]: %v", offset, err)
|
||||||
|
}
|
||||||
|
log.Trace("Select [offset: %d, repos: %d]", offset, len(repos))
|
||||||
|
if len(repos) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
offset += 10
|
||||||
|
|
||||||
|
for _, repo := range repos {
|
||||||
|
if repo.Name == "." || repo.Name == ".." {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
user := new(User)
|
||||||
|
has, err := x.Where("id = ?", repo.OwnerID).Get(user)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("query owner of repository [repo_id: %d, owner_id: %d]: %v", repo.ID, repo.OwnerID, err)
|
||||||
|
} else if !has {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
repoPath := filepath.Join(setting.RepoRootPath, strings.ToLower(user.Name), strings.ToLower(repo.Name)) + ".git"
|
||||||
|
countObject, err := git.GetRepoSize(repoPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("GetRepoSize: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
repo.Size = countObject.Size + countObject.SizePack
|
||||||
|
if _, err = x.Id(repo.ID).Cols("size").Update(repo); err != nil {
|
||||||
|
return fmt.Errorf("update size: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -207,6 +207,7 @@ type Repository struct {
|
||||||
IsFork bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
IsFork bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
||||||
ForkID int64 `xorm:"INDEX"`
|
ForkID int64 `xorm:"INDEX"`
|
||||||
BaseRepo *Repository `xorm:"-"`
|
BaseRepo *Repository `xorm:"-"`
|
||||||
|
Size int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||||
|
|
||||||
Created time.Time `xorm:"-"`
|
Created time.Time `xorm:"-"`
|
||||||
CreatedUnix int64 `xorm:"INDEX"`
|
CreatedUnix int64 `xorm:"INDEX"`
|
||||||
|
@ -546,6 +547,18 @@ func (repo *Repository) IsOwnedBy(userID int64) bool {
|
||||||
return repo.OwnerID == userID
|
return repo.OwnerID == userID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateSize updates the repository size, calculating it using git.GetRepoSize
|
||||||
|
func (repo *Repository) UpdateSize() error {
|
||||||
|
repoInfoSize, err := git.GetRepoSize(repo.RepoPath())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("UpdateSize: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repo.Size = repoInfoSize.Size + repoInfoSize.SizePack
|
||||||
|
_, err = x.ID(repo.ID).Cols("size").Update(repo)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// CanBeForked returns true if repository meets the requirements of being forked.
|
// CanBeForked returns true if repository meets the requirements of being forked.
|
||||||
func (repo *Repository) CanBeForked() bool {
|
func (repo *Repository) CanBeForked() bool {
|
||||||
return !repo.IsBare
|
return !repo.IsBare
|
||||||
|
@ -810,6 +823,10 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = repo.UpdateSize(); err != nil {
|
||||||
|
log.Error(4, "Failed to update size for repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if opts.IsMirror {
|
if opts.IsMirror {
|
||||||
if _, err = x.InsertOne(&Mirror{
|
if _, err = x.InsertOne(&Mirror{
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
|
@ -1464,6 +1481,10 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
|
||||||
return fmt.Errorf("updateRepository[%d]: %v", forkRepos[i].ID, err)
|
return fmt.Errorf("updateRepository[%d]: %v", forkRepos[i].ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = repo.UpdateSize(); err != nil {
|
||||||
|
log.Error(4, "Failed to update size for repository: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -2171,6 +2192,10 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = repo.UpdateSize(); err != nil {
|
||||||
|
log.Error(4, "Failed to update size for repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Copy LFS meta objects in new session
|
// Copy LFS meta objects in new session
|
||||||
sess2 := x.NewSession()
|
sess2 := x.NewSession()
|
||||||
defer sessionRelease(sess2)
|
defer sessionRelease(sess2)
|
||||||
|
|
|
@ -147,6 +147,11 @@ func (m *Mirror) runSync() bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := m.Repo.UpdateSize(); err != nil {
|
||||||
|
log.Error(4, "Failed to update size for mirror repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if m.Repo.HasWiki() {
|
if m.Repo.HasWiki() {
|
||||||
if _, stderr, err := process.GetManager().ExecDir(
|
if _, stderr, err := process.GetManager().ExecDir(
|
||||||
timeout, wikiPath, fmt.Sprintf("Mirror.runSync: %s", wikiPath),
|
timeout, wikiPath, fmt.Sprintf("Mirror.runSync: %s", wikiPath),
|
||||||
|
|
|
@ -101,6 +101,10 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||||
return fmt.Errorf("GetRepositoryByName: %v", err)
|
return fmt.Errorf("GetRepositoryByName: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = repo.UpdateSize(); err != nil {
|
||||||
|
log.Error(4, "Failed to update size for repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Push tags.
|
// Push tags.
|
||||||
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
|
||||||
if err := CommitRepoAction(CommitRepoActionOptions{
|
if err := CommitRepoAction(CommitRepoActionOptions{
|
||||||
|
|
|
@ -82,6 +82,9 @@ func NewFuncMap() []template.FuncMap {
|
||||||
"DateFmtShort": func(t time.Time) string {
|
"DateFmtShort": func(t time.Time) string {
|
||||||
return t.Format("Jan 02, 2006")
|
return t.Format("Jan 02, 2006")
|
||||||
},
|
},
|
||||||
|
"SizeFmt": func(s int64) string {
|
||||||
|
return base.FileSize(s)
|
||||||
|
},
|
||||||
"List": List,
|
"List": List,
|
||||||
"SubStr": func(str string, start, length int) string {
|
"SubStr": func(str string, start, length int) string {
|
||||||
if len(str) == 0 {
|
if len(str) == 0 {
|
||||||
|
|
|
@ -1119,6 +1119,7 @@ repos.private = Private
|
||||||
repos.watches = Watches
|
repos.watches = Watches
|
||||||
repos.stars = Stars
|
repos.stars = Stars
|
||||||
repos.issues = Issues
|
repos.issues = Issues
|
||||||
|
repos.size = Size
|
||||||
|
|
||||||
auths.auth_manage_panel = Authentication Manage Panel
|
auths.auth_manage_panel = Authentication Manage Panel
|
||||||
auths.new = Add New Source
|
auths.new = Add New Source
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
<th>{{.i18n.Tr "admin.repos.watches"}}</th>
|
<th>{{.i18n.Tr "admin.repos.watches"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.repos.stars"}}</th>
|
<th>{{.i18n.Tr "admin.repos.stars"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.repos.issues"}}</th>
|
<th>{{.i18n.Tr "admin.repos.issues"}}</th>
|
||||||
|
<th>{{.i18n.Tr "admin.repos.size"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.users.created"}}</th>
|
<th>{{.i18n.Tr "admin.users.created"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.notices.op"}}</th>
|
<th>{{.i18n.Tr "admin.notices.op"}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
<td>{{.NumWatches}}</td>
|
<td>{{.NumWatches}}</td>
|
||||||
<td>{{.NumStars}}</td>
|
<td>{{.NumStars}}</td>
|
||||||
<td>{{.NumIssues}}</td>
|
<td>{{.NumIssues}}</td>
|
||||||
|
<td>{{SizeFmt .Size}}</td>
|
||||||
<td><span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span></td>
|
<td><span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span></td>
|
||||||
<td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Current}}" data-id="{{.ID}}"><i class="trash icon text red"></i></a></td>
|
<td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Current}}" data-id="{{.ID}}"><i class="trash icon text red"></i></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user