From ee26f042c421d90cbd3f852427de8b98f1cc71a7 Mon Sep 17 00:00:00 2001
From: guillep2k <18600385+guillep2k@users.noreply.github.com>
Date: Fri, 24 Jan 2020 20:26:49 -0300
Subject: [PATCH] Fix file rename/copy not supported by indexer (#9965)

Co-authored-by: zeripath <art27@cantab.net>
---
 modules/indexer/code/git.go | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/modules/indexer/code/git.go b/modules/indexer/code/git.go
index bfa7d20438..114d5a9e6d 100644
--- a/modules/indexer/code/git.go
+++ b/modules/indexer/code/git.go
@@ -116,7 +116,12 @@ func nonGenesisChanges(repo *models.Repository, revision string) (*repoChanges,
 		if len(line) == 0 {
 			continue
 		}
-		filename := strings.TrimSpace(line[1:])
+		fields := strings.Split(line, "\t")
+		if len(fields) < 2 {
+			log.Warn("Unparseable output for diff --name-status: `%s`)", line)
+			continue
+		}
+		filename := fields[1]
 		if len(filename) == 0 {
 			continue
 		} else if filename[0] == '"' {
@@ -126,11 +131,31 @@ func nonGenesisChanges(repo *models.Repository, revision string) (*repoChanges,
 			}
 		}
 
-		switch status := line[0]; status {
+		switch status := fields[0][0]; status {
 		case 'M', 'A':
 			updatedFilenames = append(updatedFilenames, filename)
 		case 'D':
 			changes.RemovedFilenames = append(changes.RemovedFilenames, filename)
+		case 'R', 'C':
+			if len(fields) < 3 {
+				log.Warn("Unparseable output for diff --name-status: `%s`)", line)
+				continue
+			}
+			dest := fields[2]
+			if len(dest) == 0 {
+				log.Warn("Unparseable output for diff --name-status: `%s`)", line)
+				continue
+			}
+			if dest[0] == '"' {
+				dest, err = strconv.Unquote(dest)
+				if err != nil {
+					return nil, err
+				}
+			}
+			if status == 'R' {
+				changes.RemovedFilenames = append(changes.RemovedFilenames, filename)
+			}
+			updatedFilenames = append(updatedFilenames, dest)
 		default:
 			log.Warn("Unrecognized status: %c (line=%s)", status, line)
 		}