diff --git a/go.mod b/go.mod index 97fa29a8fc2a9..cfee14e8332ec 100644 --- a/go.mod +++ b/go.mod @@ -68,7 +68,7 @@ require ( github.com/mattn/go-isatty v0.0.16 github.com/mattn/go-sqlite3 v1.14.13 github.com/mholt/archiver/v3 v3.5.1 - github.com/microcosm-cc/bluemonday v1.0.19 + github.com/microcosm-cc/bluemonday v1.0.20 github.com/minio/minio-go/v7 v7.0.35 github.com/msteinert/pam v1.0.0 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 @@ -95,7 +95,7 @@ require ( go.jolheiser.com/hcaptcha v0.0.4 go.jolheiser.com/pwn v0.0.3 golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 - golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b + golang.org/x/net v0.0.0-20220927171203-f486391704dc golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 golang.org/x/text v0.3.7 diff --git a/go.sum b/go.sum index aca2c4b991c0b..2cdcdb4c733e6 100644 --- a/go.sum +++ b/go.sum @@ -1069,8 +1069,8 @@ github.com/mholt/acmez v1.0.4 h1:N3cE4Pek+dSolbsofIkAYz6H1d3pE+2G0os7QHslf80= github.com/mholt/acmez v1.0.4/go.mod h1:qFGLZ4u+ehWINeJZjzPlsnjJBCPAADWTcIqE/7DAYQY= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= -github.com/microcosm-cc/bluemonday v1.0.19 h1:OI7hoF5FY4pFz2VA//RN8TfM0YJ2dJcl4P4APrCWy6c= -github.com/microcosm-cc/bluemonday v1.0.19/go.mod h1:QNzV2UbLK2/53oIIwTOyLUSABMkjZ4tqiyC1g/DyqxE= +github.com/microcosm-cc/bluemonday v1.0.20 h1:flpzsq4KU3QIYAYGV/szUat7H+GPOXR0B2JU5A1Wp8Y= +github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= @@ -1710,8 +1710,9 @@ golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ= +golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/modules/packages/container/metadata.go b/modules/packages/container/metadata.go index 4222cdb30a781..fd38e67859915 100644 --- a/modules/packages/container/metadata.go +++ b/modules/packages/container/metadata.go @@ -95,7 +95,9 @@ func parseOCIImageConfig(r io.Reader) (*Metadata, error) { if i := strings.Index(cmd, "#(nop) "); i != -1 { cmd = strings.TrimSpace(cmd[i+7:]) } - imageLayers = append(imageLayers, cmd) + if cmd != "" { + imageLayers = append(imageLayers, cmd) + } } metadata := &Metadata{ diff --git a/modules/structs/repo.go b/modules/structs/repo.go index d3833105d7269..27e7f4618c677 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -151,13 +151,13 @@ type EditRepoOption struct { Template *bool `json:"template,omitempty"` // either `true` to enable issues for this repository or `false` to disable them. HasIssues *bool `json:"has_issues,omitempty"` - // set this structure to configure internal issue tracker (requires has_issues) + // set this structure to configure internal issue tracker InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` - // set this structure to use external issue tracker (requires has_issues) + // set this structure to use external issue tracker ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` // either `true` to enable the wiki for this repository or `false` to disable it. HasWiki *bool `json:"has_wiki,omitempty"` - // set this structure to use external wiki instead of internal (requires has_wiki) + // set this structure to use external wiki instead of internal ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"` // sets the default branch for this repository. DefaultBranch *string `json:"default_branch,omitempty"` @@ -165,25 +165,25 @@ type EditRepoOption struct { HasPullRequests *bool `json:"has_pull_requests,omitempty"` // either `true` to enable project unit, or `false` to disable them. HasProjects *bool `json:"has_projects,omitempty"` - // either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. `has_pull_requests` must be `true`. + // either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"` - // either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. `has_pull_requests` must be `true`. + // either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. AllowMerge *bool `json:"allow_merge_commits,omitempty"` - // either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging. `has_pull_requests` must be `true`. + // either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging. AllowRebase *bool `json:"allow_rebase,omitempty"` - // either `true` to allow rebase with explicit merge commits (--no-ff), or `false` to prevent rebase with explicit merge commits. `has_pull_requests` must be `true`. + // either `true` to allow rebase with explicit merge commits (--no-ff), or `false` to prevent rebase with explicit merge commits. AllowRebaseMerge *bool `json:"allow_rebase_explicit,omitempty"` - // either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging. `has_pull_requests` must be `true`. + // either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging. AllowSquash *bool `json:"allow_squash_merge,omitempty"` - // either `true` to allow mark pr as merged manually, or `false` to prevent it. `has_pull_requests` must be `true`. + // either `true` to allow mark pr as merged manually, or `false` to prevent it. AllowManualMerge *bool `json:"allow_manual_merge,omitempty"` - // either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur. + // either `true` to enable AutodetectManualMerge, or `false` to prevent it. Note: In some special cases, misjudgments can occur. AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"` - // either `true` to allow updating pull request branch by rebase, or `false` to prevent it. `has_pull_requests` must be `true`. + // either `true` to allow updating pull request branch by rebase, or `false` to prevent it. AllowRebaseUpdate *bool `json:"allow_rebase_update,omitempty"` // set to `true` to delete pr branch after merge by default DefaultDeleteBranchAfterMerge *bool `json:"default_delete_branch_after_merge,omitempty"` - // set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`. + // set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". DefaultMergeStyle *string `json:"default_merge_style,omitempty"` // set to `true` to archive this repository. Archived *bool `json:"archived,omitempty"` diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index b62395e546314..991ebf344f82b 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1898,6 +1898,7 @@ settings.confirm_delete = Delete Repository settings.add_collaborator = Add Collaborator settings.add_collaborator_success = The collaborator has been added. settings.add_collaborator_inactive_user = Can not add an inactive user as a collaborator. +settings.add_collaborator_owner = Can not add an owner as a collaborator. settings.add_collaborator_duplicate = The collaborator is already added to this repository. settings.delete_collaborator = Remove settings.collaborator_deletion = Remove Collaborator diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 6f40bb3e428b3..319c4c781a9cb 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -732,8 +732,13 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { var units []repo_model.RepoUnit var deleteUnitTypes []unit_model.Type + currHasIssues := repo.UnitEnabledCtx(ctx, unit_model.TypeIssues) + newHasIssues := currHasIssues if opts.HasIssues != nil { - if *opts.HasIssues && opts.ExternalTracker != nil && !unit_model.TypeExternalTracker.UnitGlobalDisabled() { + newHasIssues = *opts.HasIssues + } + if currHasIssues || newHasIssues { + if newHasIssues && opts.ExternalTracker != nil && !unit_model.TypeExternalTracker.UnitGlobalDisabled() { // Check that values are valid if !validation.IsValidExternalURL(opts.ExternalTracker.ExternalTrackerURL) { err := fmt.Errorf("External tracker URL not valid") @@ -756,7 +761,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { }, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeIssues) - } else if *opts.HasIssues && opts.ExternalTracker == nil && !unit_model.TypeIssues.UnitGlobalDisabled() { + } else if newHasIssues && opts.ExternalTracker == nil && !unit_model.TypeIssues.UnitGlobalDisabled() { // Default to built-in tracker var config *repo_model.IssuesConfig @@ -783,7 +788,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { Config: config, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalTracker) - } else if !*opts.HasIssues { + } else if !newHasIssues { if !unit_model.TypeExternalTracker.UnitGlobalDisabled() { deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalTracker) } @@ -793,8 +798,13 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } } + currHasWiki := repo.UnitEnabledCtx(ctx, unit_model.TypeWiki) + newHasWiki := currHasWiki if opts.HasWiki != nil { - if *opts.HasWiki && opts.ExternalWiki != nil && !unit_model.TypeExternalWiki.UnitGlobalDisabled() { + newHasWiki = *opts.HasWiki + } + if currHasWiki || newHasWiki { + if newHasWiki && opts.ExternalWiki != nil && !unit_model.TypeExternalWiki.UnitGlobalDisabled() { // Check that values are valid if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) { err := fmt.Errorf("External wiki URL not valid") @@ -810,7 +820,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { }, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeWiki) - } else if *opts.HasWiki && opts.ExternalWiki == nil && !unit_model.TypeWiki.UnitGlobalDisabled() { + } else if newHasWiki && opts.ExternalWiki == nil && !unit_model.TypeWiki.UnitGlobalDisabled() { config := &repo_model.UnitConfig{} units = append(units, repo_model.RepoUnit{ RepoID: repo.ID, @@ -818,7 +828,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { Config: config, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki) - } else if !*opts.HasWiki { + } else if !newHasWiki { if !unit_model.TypeExternalWiki.UnitGlobalDisabled() { deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki) } @@ -828,8 +838,13 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } } + currHasPullRequests := repo.UnitEnabledCtx(ctx, unit_model.TypePullRequests) + newHasPullRequests := currHasPullRequests if opts.HasPullRequests != nil { - if *opts.HasPullRequests && !unit_model.TypePullRequests.UnitGlobalDisabled() { + newHasPullRequests = *opts.HasPullRequests + } + if currHasPullRequests || newHasPullRequests { + if newHasPullRequests && !unit_model.TypePullRequests.UnitGlobalDisabled() { // We do allow setting individual PR settings through the API, so // we get the config settings and then set them // if those settings were provided in the opts. @@ -889,7 +904,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { Type: unit_model.TypePullRequests, Config: config, }) - } else if !*opts.HasPullRequests && !unit_model.TypePullRequests.UnitGlobalDisabled() { + } else if !newHasPullRequests && !unit_model.TypePullRequests.UnitGlobalDisabled() { deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePullRequests) } } diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index 267940c8d2e04..e7abec0d3e895 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -917,6 +917,19 @@ func CollaborationPost(ctx *context.Context) { return } + // find the owner team of the organization the repo belongs too and + // check if the user we're trying to add is an owner. + if ctx.Repo.Repository.Owner.IsOrganization() { + if isOwner, err := organization.IsOrganizationOwner(ctx, ctx.Repo.Repository.Owner.ID, u.ID); err != nil { + ctx.ServerError("IsOrganizationOwner", err) + return + } else if isOwner { + ctx.Flash.Error(ctx.Tr("repo.settings.add_collaborator_owner")) + ctx.Redirect(setting.AppSubURL + ctx.Req.URL.EscapedPath()) + return + } + } + if err = repo_module.AddCollaborator(ctx.Repo.Repository, u); err != nil { ctx.ServerError("AddCollaborator", err) return diff --git a/services/auth/reverseproxy.go b/services/auth/reverseproxy.go index d9d1b63e8fea3..8dec1c8ea778f 100644 --- a/services/auth/reverseproxy.go +++ b/services/auth/reverseproxy.go @@ -37,11 +37,7 @@ type ReverseProxy struct{} // getUserName extracts the username from the "setting.ReverseProxyAuthUser" header func (r *ReverseProxy) getUserName(req *http.Request) string { - webAuthUser := strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuthUser)) - if len(webAuthUser) == 0 { - return "" - } - return webAuthUser + return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuthUser)) } // Name represents the name of auth method @@ -49,14 +45,14 @@ func (r *ReverseProxy) Name() string { return ReverseProxyMethodName } -// Verify extracts the username from the "setting.ReverseProxyAuthUser" header +// getUserFromAuthUser extracts the username from the "setting.ReverseProxyAuthUser" header // of the request and returns the corresponding user object for that name. // Verification of header data is not performed as it should have already been done by -// the revese proxy. +// the reverse proxy. // If a username is available in the "setting.ReverseProxyAuthUser" header an existing // user object is returned (populated with username or email found in header). // Returns nil if header is empty. -func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { +func (r *ReverseProxy) getUserFromAuthUser(req *http.Request) *user_model.User { username := r.getUserName(req) if len(username) == 0 { return nil @@ -71,6 +67,54 @@ func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store Da } user = r.newUser(req) } + return user +} + +// getEmail extracts the email from the "setting.ReverseProxyAuthEmail" header +func (r *ReverseProxy) getEmail(req *http.Request) string { + return strings.TrimSpace(req.Header.Get(setting.ReverseProxyAuthEmail)) +} + +// getUserFromAuthEmail extracts the username from the "setting.ReverseProxyAuthEmail" header +// of the request and returns the corresponding user object for that email. +// Verification of header data is not performed as it should have already been done by +// the reverse proxy. +// If an email is available in the "setting.ReverseProxyAuthEmail" header an existing +// user object is returned (populated with the email found in header). +// Returns nil if header is empty or if "setting.EnableReverseProxyEmail" is disabled. +func (r *ReverseProxy) getUserFromAuthEmail(req *http.Request) *user_model.User { + if !setting.Service.EnableReverseProxyEmail { + return nil + } + email := r.getEmail(req) + if len(email) == 0 { + return nil + } + log.Trace("ReverseProxy Authorization: Found email: %s", email) + + user, err := user_model.GetUserByEmail(email) + if err != nil { + // Do not allow auto-registration, we don't have a username here + if !user_model.IsErrUserNotExist(err) { + log.Error("GetUserByEmail: %v", err) + } + return nil + } + return user +} + +// Verify attempts to load a user object based on headers sent by the reverse proxy. +// First it will attempt to load it based on the username (see docs for getUserFromAuthUser), +// and failing that it will attempt to load it based on the email (see docs for getUserFromAuthEmail). +// Returns nil if the headers are empty or the user is not found. +func (r *ReverseProxy) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) *user_model.User { + user := r.getUserFromAuthUser(req) + if user == nil { + user = r.getUserFromAuthEmail(req) + if user == nil { + return nil + } + } // Make sure requests to API paths, attachment downloads, git and LFS do not create a new session if !middleware.IsAPIPath(req) && !isAttachmentDownload(req) && !isGitRawReleaseOrLFSPath(req) { diff --git a/templates/package/content/container.tmpl b/templates/package/content/container.tmpl index 939dfe40208ae..a79963e732ba0 100644 --- a/templates/package/content/container.tmpl +++ b/templates/package/content/container.tmpl @@ -47,7 +47,7 @@ {{if .PackageDescriptor.Metadata.ImageLayers}}

{{.locale.Tr "packages.container.layers"}}

- +
{{range .PackageDescriptor.Metadata.ImageLayers}} @@ -61,7 +61,7 @@ {{if .PackageDescriptor.Metadata.Labels}}

{{.locale.Tr "packages.container.labels"}}

-
+
diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl index 8ece768832fb7..da37aaa9b323f 100644 --- a/templates/repo/commit_page.tmpl +++ b/templates/repo/commit_page.tmpl @@ -1,7 +1,7 @@ {{template "base/head" .}}
{{template "repo/header" .}} -
+
{{$class := ""}} {{if .Commit.Signature}} {{$class = (printf "%s%s" $class " isSigned")}} diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index 51769eb95393e..4624a53ba38d1 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -14,6 +14,11 @@ {{else}}
+ + {{/* the icon meaning is reversed here, "octicon-sidebar-collapse" means show the file tree */}} + {{svg "octicon-sidebar-collapse" 16 "icon hide"}} + {{svg "octicon-sidebar-expand" 16 "icon"}} +
{{svg "octicon-diff" 16 "mr-2"}}{{.locale.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}}
@@ -31,145 +36,151 @@ {{end}}
-
    - {{range .Diff.Files}} -
  1. -
    - {{if .IsBin}} - - {{$.locale.Tr "repo.diff.bin"}} - - {{else}} - {{template "repo/diff/stats" dict "file" . "root" $}} - {{end}} -
    - -   - {{.Name}} -
  2. - {{end}} - {{if .Diff.IsIncomplete}} -
  3. - {{$.locale.Tr "repo.diff.too_many_files"}} - {{.locale.Tr "repo.diff.show_more"}} - -
  4. - {{end}} -
-
- {{range $file := .Diff.Files}} - {{/*notice: the index of Diff.Files should not be used for element ID, because the index will be restarted from 0 when doing load-more for PRs with a lot of files*/}} - {{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}} - {{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}} - {{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}} - {{$isCsv := (call $.IsCsvFile $file)}} - {{$showFileViewToggle := or $isImage (and (not $file.IsIncomplete) $isCsv)}} -
-

-
- - {{if $file.ShouldBeHidden}} - {{svg "octicon-chevron-right" 18}} - {{else}} - {{svg "octicon-chevron-down" 18}} - {{end}} - -
- {{if $file.IsBin}} - - {{$.locale.Tr "repo.diff.bin"}} - - {{else}} - {{template "repo/diff/stats" dict "file" . "root" $}} - {{end}} -
- {{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}{{if .IsLFSFile}} ({{$.locale.Tr "repo.stored_lfs"}}){{end}} - {{if $file.IsGenerated}} - {{$.locale.Tr "repo.diff.generated"}} - {{end}} - {{if $file.IsVendored}} - {{$.locale.Tr "repo.diff.vendored"}} - {{end}} -
-
- {{if $showFileViewToggle}} -
- {{svg "octicon-code"}} - {{svg "octicon-file"}} -
- {{end}} - {{if $file.IsProtected}} - {{$.locale.Tr "repo.diff.protected"}} - {{end}} - {{if not (or $file.IsIncomplete $file.IsBin $file.IsSubmodule)}} - {{$.locale.Tr "repo.unescape_control_characters"}} - - {{end}} - {{if and (not $file.IsSubmodule) (not $.PageIsWiki)}} - {{if $file.IsDeleted}} - {{$.locale.Tr "repo.diff.view_file"}} - {{else}} - {{$.locale.Tr "repo.diff.view_file"}} - {{end}} - {{end}} - {{if and $.IsSigned $.PageIsPullFiles (not $.IsArchived)}} - {{if $file.HasChangedSinceLastReview}} - {{$.locale.Tr "repo.pulls.has_changed_since_last_review"}} - {{end}} - - {{end}} -
-

-
-
- {{if or $file.IsIncomplete $file.IsBin}} -
- {{if $file.IsIncomplete}} - {{if $file.IsIncompleteLineTooLong}} - {{$.locale.Tr "repo.diff.file_suppressed_line_too_long"}} + +
+
+
+
+ {{range $i, $file := .Diff.Files}} + {{/*notice: the index of Diff.Files should not be used for element ID, because the index will be restarted from 0 when doing load-more for PRs with a lot of files*/}} + {{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}} + {{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}} + {{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}} + {{$isCsv := (call $.IsCsvFile $file)}} + {{$showFileViewToggle := or $isImage (and (not $file.IsIncomplete) $isCsv)}} +
+

+
+ + {{if $file.ShouldBeHidden}} + {{svg "octicon-chevron-right" 18}} {{else}} - {{$.locale.Tr "repo.diff.file_suppressed"}} - {{$.locale.Tr "repo.diff.load"}} + {{svg "octicon-chevron-down" 18}} {{end}} - {{else}} - {{$.locale.Tr "repo.diff.bin_not_shown"}} + +
+ {{if $file.IsBin}} + + {{$.locale.Tr "repo.diff.bin"}} + + {{else}} + {{template "repo/diff/stats" dict "file" . "root" $}} + {{end}} +
+ {{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}{{if .IsLFSFile}} ({{$.locale.Tr "repo.stored_lfs"}}){{end}} + {{if $file.IsGenerated}} + {{$.locale.Tr "repo.diff.generated"}} + {{end}} + {{if $file.IsVendored}} + {{$.locale.Tr "repo.diff.vendored"}} {{end}}
- {{else}} -

{{.locale.Tr "packages.container.labels.key"}}
- {{if $.IsSplitStyle}} - {{template "repo/diff/section_split" dict "file" . "root" $}} - {{else}} - {{template "repo/diff/section_unified" dict "file" . "root" $}} +
+ {{if $showFileViewToggle}} +
+ {{svg "octicon-code"}} + {{svg "octicon-file"}} +
{{end}} -
- {{end}} -
- {{if $showFileViewToggle}} -
- - {{if $isImage}} - {{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}} + {{if $file.IsProtected}} + {{$.locale.Tr "repo.diff.protected"}} + {{end}} + {{if not (or $file.IsIncomplete $file.IsBin $file.IsSubmodule)}} + {{$.locale.Tr "repo.unescape_control_characters"}} + + {{end}} + {{if and (not $file.IsSubmodule) (not $.PageIsWiki)}} + {{if $file.IsDeleted}} + {{$.locale.Tr "repo.diff.view_file"}} + {{else}} + {{$.locale.Tr "repo.diff.view_file"}} + {{end}} + {{end}} + {{if and $.IsSigned $.PageIsPullFiles (not $.IsArchived)}} + {{if $file.HasChangedSinceLastReview}} + {{$.locale.Tr "repo.pulls.has_changed_since_last_review"}} + {{end}} + + {{end}} + + +
+
+ {{if or $file.IsIncomplete $file.IsBin}} +
+ {{if $file.IsIncomplete}} + {{if $file.IsIncompleteLineTooLong}} + {{$.locale.Tr "repo.diff.file_suppressed_line_too_long"}} + {{else}} + {{$.locale.Tr "repo.diff.file_suppressed"}} + {{$.locale.Tr "repo.diff.load"}} + {{end}} + {{else}} + {{$.locale.Tr "repo.diff.bin_not_shown"}} + {{end}} +
{{else}} - {{template "repo/diff/csv_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}} +
+ {{if $.IsSplitStyle}} + {{template "repo/diff/section_split" dict "file" . "root" $}} + {{else}} + {{template "repo/diff/section_unified" dict "file" . "root" $}} + {{end}} +
{{end}} - +
+ {{if $showFileViewToggle}} +
+ + {{if $isImage}} + {{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}} + {{else}} + {{template "repo/diff/csv_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}} + {{end}} +
+
+ {{end}} - {{end}} - - - {{end}} + + {{end}} - {{if .Diff.IsIncomplete}} -
-

- {{$.locale.Tr "repo.diff.too_many_files"}} - {{.locale.Tr "repo.diff.show_more"}} -

+ {{if .Diff.IsIncomplete}} +
+

+ {{$.locale.Tr "repo.diff.too_many_files"}} + {{.locale.Tr "repo.diff.show_more"}} +

+
+ {{end}}
- {{end}} {{if not $.Repository.IsArchived}} diff --git a/templates/repo/diff/compare.tmpl b/templates/repo/diff/compare.tmpl index 029e7717a44e8..e0e6837203d1e 100644 --- a/templates/repo/diff/compare.tmpl +++ b/templates/repo/diff/compare.tmpl @@ -1,7 +1,7 @@ {{template "base/head" .}}
{{template "repo/header" .}} -
+

{{if and $.PageIsComparePull $.IsSigned (not .Repository.IsArchived)}} diff --git a/templates/repo/diff/options_dropdown.tmpl b/templates/repo/diff/options_dropdown.tmpl index 18fa100dcfa6d..2cb5abcb36d4f 100644 --- a/templates/repo/diff/options_dropdown.tmpl +++ b/templates/repo/diff/options_dropdown.tmpl @@ -1,7 +1,7 @@