From a36c620583b9caa3133b714f47b6de32754e136c Mon Sep 17 00:00:00 2001
From: Yevhen Pavlov <yevhen.pavlov.ua@gmail.com>
Date: Mon, 29 May 2023 20:56:08 +0300
Subject: [PATCH] Display file mode for new file and file mode changes (#24966)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This MR introduces the addition of file mode display support for both
new file creation and file mode changes, following a similar approach as
GitLab.

GitLab:

![изображение](https://github.com/go-gitea/gitea/assets/1969460/4c0d0d74-30b2-486c-ac12-ef2355b04c96)


Gitea:

![изображение](https://github.com/go-gitea/gitea/assets/1969460/8237fe99-2507-42c0-a40c-cd52ad355ab7)

Replaces: https://github.com/go-gitea/gitea/pull/23159
Closes: https://github.com/go-gitea/gitea/issues/23021

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: Giteabot <teabot@gitea.io>
---
 services/gitdiff/gitdiff.go  | 27 +++++++++++++++++++++++----
 templates/repo/diff/box.tmpl |  5 +++++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index 73474cf248c1..b6a75f60982f 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -371,6 +371,8 @@ type DiffFile struct {
 	IsViewed                  bool // User specific
 	HasChangedSinceLastReview bool // User specific
 	Language                  string
+	Mode                      string
+	OldMode                   string
 }
 
 // GetType returns type of diff file.
@@ -501,6 +503,11 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader, ski
 		}
 		return diff, err
 	}
+
+	prepareValue := func(s, p string) string {
+		return strings.TrimSpace(strings.TrimPrefix(s, p))
+	}
+
 parsingLoop:
 	for {
 		// 1. A patch file always begins with `diff --git ` + `a/path b/path` (possibly quoted)
@@ -585,11 +592,20 @@ parsingLoop:
 				}
 				break parsingLoop
 			}
+
 			switch {
 			case strings.HasPrefix(line, cmdDiffHead):
 				break curFileLoop
 			case strings.HasPrefix(line, "old mode ") ||
 				strings.HasPrefix(line, "new mode "):
+
+				if strings.HasPrefix(line, "old mode ") {
+					curFile.OldMode = prepareValue(line, "old mode ")
+				}
+				if strings.HasPrefix(line, "new mode ") {
+					curFile.Mode = prepareValue(line, "new mode ")
+				}
+
 				if strings.HasSuffix(line, " 160000\n") {
 					curFile.IsSubmodule = true
 				}
@@ -597,31 +613,34 @@ parsingLoop:
 				curFile.IsRenamed = true
 				curFile.Type = DiffFileRename
 				if curFile.IsAmbiguous {
-					curFile.OldName = line[len("rename from ") : len(line)-1]
+					curFile.OldName = prepareValue(line, "rename from ")
 				}
 			case strings.HasPrefix(line, "rename to "):
 				curFile.IsRenamed = true
 				curFile.Type = DiffFileRename
 				if curFile.IsAmbiguous {
-					curFile.Name = line[len("rename to ") : len(line)-1]
+					curFile.Name = prepareValue(line, "rename to ")
 					curFile.IsAmbiguous = false
 				}
 			case strings.HasPrefix(line, "copy from "):
 				curFile.IsRenamed = true
 				curFile.Type = DiffFileCopy
 				if curFile.IsAmbiguous {
-					curFile.OldName = line[len("copy from ") : len(line)-1]
+					curFile.OldName = prepareValue(line, "copy from ")
 				}
 			case strings.HasPrefix(line, "copy to "):
 				curFile.IsRenamed = true
 				curFile.Type = DiffFileCopy
 				if curFile.IsAmbiguous {
-					curFile.Name = line[len("copy to ") : len(line)-1]
+					curFile.Name = prepareValue(line, "copy to ")
 					curFile.IsAmbiguous = false
 				}
 			case strings.HasPrefix(line, "new file"):
 				curFile.Type = DiffFileAdd
 				curFile.IsCreated = true
+				if strings.HasPrefix(line, "new file mode ") {
+					curFile.Mode = prepareValue(line, "new file mode ")
+				}
 				if strings.HasSuffix(line, " 160000\n") {
 					curFile.IsSubmodule = true
 				}
diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl
index 292a7dd2bd33..132f999808cc 100644
--- a/templates/repo/diff/box.tmpl
+++ b/templates/repo/diff/box.tmpl
@@ -113,6 +113,11 @@
 									{{if $file.IsVendored}}
 										<span class="ui label gt-ml-3">{{$.locale.Tr "repo.diff.vendored"}}</span>
 									{{end}}
+									{{if and $file.Mode $file.OldMode}}
+										<span class="gt-ml-4 gt-mono">{{$file.OldMode}} &rarr; {{$file.Mode}}</span>
+									{{else if $file.Mode}}
+										<span class="gt-ml-4 gt-mono">{{$file.Mode}}</span>
+									{{end}}
 								</div>
 								<div class="diff-file-header-actions gt-df gt-ac">
 									{{if $showFileViewToggle}}