mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-11-04 08:21:11 +00:00 
			
		
		
		
	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
					
				
			
		
					 8 changed files with 119 additions and 0 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue