]> source.dussan.org Git - gitea.git/commitdiff
Repo size in admin panel (#1482)
authorJonas <cez81@users.noreply.github.com>
Tue, 11 Apr 2017 13:30:15 +0000 (15:30 +0200)
committerBo-Yi Wu <appleboy.tw@gmail.com>
Tue, 11 Apr 2017 13:30:15 +0000 (21:30 +0800)
* 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

models/migrations/migrations.go
models/migrations/v28.go [new file with mode: 0644]
models/repo.go
models/repo_mirror.go
models/update.go
modules/templates/helper.go
options/locale/locale_en-US.ini
templates/admin/repo/list.tmpl

index fee0fef79c88ff6a887e98998f4dd56e13fecd97..fb7b66cd00bf2f209e7e8905a6f96f97ea97d7f8 100644 (file)
@@ -104,6 +104,8 @@ var migrations = []Migration{
        NewMigration("generate and migrate repo and wiki Git hooks", generateAndMigrateGitHookChains),
        // v27 -> v28
        NewMigration("change mirror interval from hours to time.Duration", convertIntervalToDuration),
+       // v28 -> v29
+       NewMigration("add field for repo size", addRepoSize),
 }
 
 // Migrate database to current version
diff --git a/models/migrations/v28.go b/models/migrations/v28.go
new file mode 100644 (file)
index 0000000..f7b4cd6
--- /dev/null
@@ -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
+}
index c654356916f7e8466225bf6eb0dcdcef9a39e4af..a35a7597f42ab6069e5d8a21596747e6aa307a6e 100644 (file)
@@ -207,6 +207,7 @@ type Repository struct {
        IsFork   bool        `xorm:"INDEX NOT NULL DEFAULT false"`
        ForkID   int64       `xorm:"INDEX"`
        BaseRepo *Repository `xorm:"-"`
+       Size     int64       `xorm:"NOT NULL DEFAULT 0"`
 
        Created     time.Time `xorm:"-"`
        CreatedUnix int64     `xorm:"INDEX"`
@@ -546,6 +547,18 @@ func (repo *Repository) IsOwnedBy(userID int64) bool {
        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.
 func (repo *Repository) CanBeForked() bool {
        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 _, err = x.InsertOne(&Mirror{
                        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)
                        }
                }
+
+               if err = repo.UpdateSize(); err != nil {
+                       log.Error(4, "Failed to update size for repository: %v", err)
+               }
        }
 
        return nil
@@ -2171,6 +2192,10 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
                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
        sess2 := x.NewSession()
        defer sessionRelease(sess2)
index 67ae449bdeb598aa3032f85ca0ff0ab530c4cabf..8a9787925386224841dc0a5337745baa48088f16 100644 (file)
@@ -147,6 +147,11 @@ func (m *Mirror) runSync() bool {
                }
                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 _, stderr, err := process.GetManager().ExecDir(
                        timeout, wikiPath, fmt.Sprintf("Mirror.runSync: %s", wikiPath),
index 3cb0608594fffd6096c979fc2467e719d46e0de5..b3a8a1c9fbc7886bc4e3d9c4497c3ae7a6c7881e 100644 (file)
@@ -101,6 +101,10 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
                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.
        if strings.HasPrefix(opts.RefFullName, git.TagPrefix) {
                if err := CommitRepoAction(CommitRepoActionOptions{
index 2e756ce3648163f3971738fc7bd32d885253bbbd..51877f80398941fe88a559803c0dfd25881d10a0 100644 (file)
@@ -82,6 +82,9 @@ func NewFuncMap() []template.FuncMap {
                "DateFmtShort": func(t time.Time) string {
                        return t.Format("Jan 02, 2006")
                },
+               "SizeFmt": func(s int64) string {
+                       return base.FileSize(s)
+               },
                "List": List,
                "SubStr": func(str string, start, length int) string {
                        if len(str) == 0 {
index cfb4da30aefa892804875a9d38b5eea365604d52..cb39ec857129bfc3a1d0a6643db437a7a4499a01 100644 (file)
@@ -1119,6 +1119,7 @@ repos.private = Private
 repos.watches = Watches
 repos.stars = Stars
 repos.issues = Issues
+repos.size = Size
 
 auths.auth_manage_panel = Authentication Manage Panel
 auths.new = Add New Source
index ffdbd5bfb896edc4e3bb6c7862da247aa3b81013..aeaecf8dfbdb981a8a9965ca70b51cb2ed249fa2 100644 (file)
@@ -20,6 +20,7 @@
                                                <th>{{.i18n.Tr "admin.repos.watches"}}</th>
                                                <th>{{.i18n.Tr "admin.repos.stars"}}</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.notices.op"}}</th>
                                        </tr>
@@ -34,6 +35,7 @@
                                                        <td>{{.NumWatches}}</td>
                                                        <td>{{.NumStars}}</td>
                                                        <td>{{.NumIssues}}</td>
+                                                       <td>{{SizeFmt .Size}}</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>
                                                </tr>