Skip to content

Commit f89cabe

Browse files
authored
Merge branch 'master' into route-lfs-internally-fix-go-gitea#732
2 parents a96b3c4 + 8eba27c commit f89cabe

File tree

9 files changed

+105
-19
lines changed

9 files changed

+105
-19
lines changed

custom/conf/app.ini.sample

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ SESSION_LIFE_TIME = 86400
505505
[picture]
506506
AVATAR_UPLOAD_PATH = data/avatars
507507
REPOSITORY_AVATAR_UPLOAD_PATH = data/repo-avatars
508+
; How Gitea deals with missing repository avatars
509+
; none = no avatar will be displayed; random = random avatar will be displayed; image = default image will be used
510+
REPOSITORY_AVATAR_FALLBACK = none
511+
REPOSITORY_AVATAR_FALLBACK_IMAGE = /img/repo_default.png
508512
; Max Width and Height of uploaded avatars.
509513
; This is to limit the amount of RAM used when resizing the image.
510514
AVATAR_MAX_WIDTH = 4096

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
292292
[http://www.libravatar.org](http://www.libravatar.org)).
293293
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store user avatar image files.
294294
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: Path to store repository avatar image files.
295+
- `REPOSITORY_AVATAR_FALLBACK`: **none**: How Gitea deals with missing repository avatars
296+
- none = no avatar will be displayed
297+
- random = random avatar will be generated
298+
- image = default image will be used (which is set in `REPOSITORY_AVATAR_DEFAULT_IMAGE`)
299+
- `REPOSITORY_AVATAR_FALLBACK_IMAGE`: **/img/repo_default.png**: Image used as default repository avatar (if `REPOSITORY_AVATAR_FALLBACK` is set to image and none was uploaded)
295300
- `AVATAR_MAX_WIDTH`: **4096**: Maximum avatar image width in pixels.
296301
- `AVATAR_MAX_HEIGHT`: **3072**: Maximum avatar image height in pixels.
297302
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1Mb): Maximum avatar image file size in bytes.

models/repo.go

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,17 +2528,78 @@ func (repo *Repository) CustomAvatarPath() string {
25282528
return filepath.Join(setting.RepositoryAvatarUploadPath, repo.Avatar)
25292529
}
25302530

2531-
// RelAvatarLink returns a relative link to the user's avatar.
2532-
// The link a sub-URL to this site
2533-
// Since Gravatar support not needed here - just check for image path.
2531+
// GenerateRandomAvatar generates a random avatar for repository.
2532+
func (repo *Repository) GenerateRandomAvatar() error {
2533+
return repo.generateRandomAvatar(x)
2534+
}
2535+
2536+
func (repo *Repository) generateRandomAvatar(e Engine) error {
2537+
idToString := fmt.Sprintf("%d", repo.ID)
2538+
2539+
seed := idToString
2540+
img, err := avatar.RandomImage([]byte(seed))
2541+
if err != nil {
2542+
return fmt.Errorf("RandomImage: %v", err)
2543+
}
2544+
2545+
repo.Avatar = idToString
2546+
if err = os.MkdirAll(filepath.Dir(repo.CustomAvatarPath()), os.ModePerm); err != nil {
2547+
return fmt.Errorf("MkdirAll: %v", err)
2548+
}
2549+
fw, err := os.Create(repo.CustomAvatarPath())
2550+
if err != nil {
2551+
return fmt.Errorf("Create: %v", err)
2552+
}
2553+
defer fw.Close()
2554+
2555+
if err = png.Encode(fw, img); err != nil {
2556+
return fmt.Errorf("Encode: %v", err)
2557+
}
2558+
log.Info("New random avatar created for repository: %d", repo.ID)
2559+
2560+
if _, err := e.ID(repo.ID).Cols("avatar").NoAutoTime().Update(repo); err != nil {
2561+
return err
2562+
}
2563+
2564+
return nil
2565+
}
2566+
2567+
// RemoveRandomAvatars removes the randomly generated avatars that were created for repositories
2568+
func RemoveRandomAvatars() error {
2569+
var (
2570+
err error
2571+
)
2572+
err = x.
2573+
Where("id > 0").BufferSize(setting.IterateBufferSize).
2574+
Iterate(new(Repository),
2575+
func(idx int, bean interface{}) error {
2576+
repository := bean.(*Repository)
2577+
stringifiedID := strconv.FormatInt(repository.ID, 10)
2578+
if repository.Avatar == stringifiedID {
2579+
return repository.DeleteAvatar()
2580+
}
2581+
return nil
2582+
})
2583+
return err
2584+
}
2585+
2586+
// RelAvatarLink returns a relative link to the repository's avatar.
25342587
func (repo *Repository) RelAvatarLink() string {
2588+
25352589
// If no avatar - path is empty
25362590
avatarPath := repo.CustomAvatarPath()
2537-
if len(avatarPath) <= 0 {
2538-
return ""
2539-
}
2540-
if !com.IsFile(avatarPath) {
2541-
return ""
2591+
if len(avatarPath) <= 0 || !com.IsFile(avatarPath) {
2592+
switch mode := setting.RepositoryAvatarFallback; mode {
2593+
case "image":
2594+
return setting.RepositoryAvatarFallbackImage
2595+
case "random":
2596+
if err := repo.GenerateRandomAvatar(); err != nil {
2597+
log.Error("GenerateRandomAvatar: %v", err)
2598+
}
2599+
default:
2600+
// default behaviour: do not display avatar
2601+
return ""
2602+
}
25422603
}
25432604
return setting.AppSubURL + "/repo-avatars/" + repo.Avatar
25442605
}

modules/setting/setting.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,16 +250,18 @@ var (
250250
}
251251

252252
// Picture settings
253-
AvatarUploadPath string
254-
AvatarMaxWidth int
255-
AvatarMaxHeight int
256-
GravatarSource string
257-
GravatarSourceURL *url.URL
258-
DisableGravatar bool
259-
EnableFederatedAvatar bool
260-
LibravatarService *libravatar.Libravatar
261-
AvatarMaxFileSize int64
262-
RepositoryAvatarUploadPath string
253+
AvatarUploadPath string
254+
AvatarMaxWidth int
255+
AvatarMaxHeight int
256+
GravatarSource string
257+
GravatarSourceURL *url.URL
258+
DisableGravatar bool
259+
EnableFederatedAvatar bool
260+
LibravatarService *libravatar.Libravatar
261+
AvatarMaxFileSize int64
262+
RepositoryAvatarUploadPath string
263+
RepositoryAvatarFallback string
264+
RepositoryAvatarFallbackImage string
263265

264266
// Log settings
265267
LogLevel string
@@ -842,6 +844,8 @@ func NewContext() {
842844
if !filepath.IsAbs(RepositoryAvatarUploadPath) {
843845
RepositoryAvatarUploadPath = path.Join(AppWorkPath, RepositoryAvatarUploadPath)
844846
}
847+
RepositoryAvatarFallback = sec.Key("REPOSITORY_AVATAR_FALLBACK").MustString("none")
848+
RepositoryAvatarFallbackImage = sec.Key("REPOSITORY_AVATAR_FALLBACK_IMAGE").MustString("/img/repo_default.png")
845849
AvatarMaxWidth = sec.Key("AVATAR_MAX_WIDTH").MustInt(4096)
846850
AvatarMaxHeight = sec.Key("AVATAR_MAX_HEIGHT").MustInt(3072)
847851
AvatarMaxFileSize = sec.Key("AVATAR_MAX_FILE_SIZE").MustInt64(1048576)

options/locale/locale_en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,8 @@ dashboard.delete_repo_archives = Delete all repository archives
15221522
dashboard.delete_repo_archives_success = All repository archives have been deleted.
15231523
dashboard.delete_missing_repos = Delete all repositories missing their Git files
15241524
dashboard.delete_missing_repos_success = All repositories missing their Git files have been deleted.
1525+
dashboard.delete_generated_repository_avatars = Delete generated repository avatars
1526+
dashboard.delete_generated_repository_avatars_success = Generated repository avatars were deleted.
15251527
dashboard.git_gc_repos = Garbage collect all repositories
15261528
dashboard.git_gc_repos_success = All repositories have finished garbage collection.
15271529
dashboard.resync_all_sshkeys = Update the '.ssh/authorized_keys' file with Gitea SSH keys. (Not needed for the built-in SSH server.)

public/img/repo_default.png

2.41 KB
Loading

routers/admin/admin.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ const (
125125
reinitMissingRepository
126126
syncExternalUsers
127127
gitFsck
128+
deleteGeneratedRepositoryAvatars
128129
)
129130

130131
// Dashboard show admin panel dashboard
@@ -167,6 +168,9 @@ func Dashboard(ctx *context.Context) {
167168
case gitFsck:
168169
success = ctx.Tr("admin.dashboard.git_fsck_started")
169170
go models.GitFsck()
171+
case deleteGeneratedRepositoryAvatars:
172+
success = ctx.Tr("admin.dashboard.delete_generated_repository_avatars_success")
173+
err = models.RemoveRandomAvatars()
170174
}
171175

172176
if err != nil {

templates/admin/dashboard.tmpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
<td>{{.i18n.Tr "admin.dashboard.git_fsck"}}</td>
5454
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=9">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
5555
</tr>
56+
<tr>
57+
<td>{{.i18n.Tr "admin.dashboard.delete_generated_repository_avatars"}}</td>
58+
<td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=10">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td>
59+
</tr>
5660
</tbody>
5761
</table>
5862
</div>

templates/explore/repo_list.tmpl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
{{range .Repos}}
33
<div class="item">
44
<div class="ui header">
5-
<img class="ui avatar image" src="{{.RelAvatarLink}}">
5+
{{if .RelAvatarLink}}
6+
<img class="ui avatar image" src="{{.RelAvatarLink}}">
7+
{{end}}
68
<a class="name" href="{{.Link}}">
79
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} / {{end}}{{end}}{{.Name}}
810
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}}

0 commit comments

Comments
 (0)