mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 06:21:11 +00:00 
			
		
		
		
	[GITEA] Detect file rename and show in history
- Add a indication to the file history if the file has been renamed, this indication contains a link to browse the history of the file further. - Added unit testing. - Added integration testing. - Resolves https://codeberg.org/forgejo/forgejo/issues/1279 (cherry picked from commit72c297521b) (cherry picked from commit283f964894) Conflicts: options/locale/locale_en-US.ini https://codeberg.org/forgejo/forgejo/pulls/1550 (cherry picked from commit7c30af7fde) (cherry picked from commitf3be6eb269)
This commit is contained in:
		
					parent
					
						
							
								5b7a43c43f
							
						
					
				
			
			
				commit
				
					
						78e1755b94
					
				
			
		
					 22 changed files with 140 additions and 2 deletions
				
			
		|  | @ -509,6 +509,62 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi | |||
| 	return fileStatus, nil | ||||
| } | ||||
| 
 | ||||
| func parseCommitRenames(renames *[][2]string, stdout io.Reader) { | ||||
| 	rd := bufio.NewReader(stdout) | ||||
| 	for { | ||||
| 		// Skip (R || three digits || NULL byte) | ||||
| 		_, err := rd.Discard(5) | ||||
| 		if err != nil { | ||||
| 			if err != io.EOF { | ||||
| 				log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		oldFileName, err := rd.ReadString('\x00') | ||||
| 		if err != nil { | ||||
| 			if err != io.EOF { | ||||
| 				log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		newFileName, err := rd.ReadString('\x00') | ||||
| 		if err != nil { | ||||
| 			if err != io.EOF { | ||||
| 				log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		oldFileName = strings.TrimSuffix(oldFileName, "\x00") | ||||
| 		newFileName = strings.TrimSuffix(newFileName, "\x00") | ||||
| 		*renames = append(*renames, [2]string{oldFileName, newFileName}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // GetCommitFileRenames returns the renames that the commit contains. | ||||
| func GetCommitFileRenames(ctx context.Context, repoPath, commitID string) ([][2]string, error) { | ||||
| 	renames := [][2]string{} | ||||
| 	stdout, w := io.Pipe() | ||||
| 	done := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		parseCommitRenames(&renames, stdout) | ||||
| 		close(done) | ||||
| 	}() | ||||
| 
 | ||||
| 	stderr := new(bytes.Buffer) | ||||
| 	err := NewCommand(ctx, "show", "--name-status", "--pretty=format:", "-z", "--diff-filter=R").AddDynamicArguments(commitID).Run(&RunOpts{ | ||||
| 		Dir:    repoPath, | ||||
| 		Stdout: w, | ||||
| 		Stderr: stderr, | ||||
| 	}) | ||||
| 	w.Close() // Close writer to exit parsing goroutine | ||||
| 	if err != nil { | ||||
| 		return nil, ConcatenateError(err, stderr.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	<-done | ||||
| 	return renames, nil | ||||
| } | ||||
| 
 | ||||
| // GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository. | ||||
| func GetFullCommitID(ctx context.Context, repoPath, shortID string) (string, error) { | ||||
| 	commitID, _, err := NewCommand(ctx, "rev-parse").AddDynamicArguments(shortID).RunStdString(&RunOpts{Dir: repoPath}) | ||||
|  |  | |||
|  | @ -278,3 +278,30 @@ func TestGetCommitFileStatusMerges(t *testing.T) { | |||
| 	assert.Equal(t, commitFileStatus.Removed, expected.Removed) | ||||
| 	assert.Equal(t, commitFileStatus.Modified, expected.Modified) | ||||
| } | ||||
| 
 | ||||
| func TestParseCommitRenames(t *testing.T) { | ||||
| 	testcases := []struct { | ||||
| 		output  string | ||||
| 		renames [][2]string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			output:  "R090\x00renamed.txt\x00history.txt\x00", | ||||
| 			renames: [][2]string{{"renamed.txt", "history.txt"}}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			output:  "R090\x00renamed.txt\x00history.txt\x00R000\x00corruptedstdouthere", | ||||
| 			renames: [][2]string{{"renamed.txt", "history.txt"}}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			output:  "R100\x00renamed.txt\x00history.txt\x00R001\x00readme.md\x00README.md\x00", | ||||
| 			renames: [][2]string{{"renamed.txt", "history.txt"}, {"readme.md", "README.md"}}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, testcase := range testcases { | ||||
| 		renames := [][2]string{} | ||||
| 		parseCommitRenames(&renames, strings.NewReader(testcase.output)) | ||||
| 
 | ||||
| 		assert.Equal(t, testcase.renames, renames) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue