mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Fix blame view missing lines (#22826)
Creating a new buffered reader for every part of the blame can miss lines, as it will read and buffer bytes that the next buffered reader will not get. Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							4dd7d61ac8
						
					
				
				
					commit
					87261f3fb9
				
			@@ -23,6 +23,7 @@ type BlameReader struct {
 | 
				
			|||||||
	cmd            *Command
 | 
						cmd            *Command
 | 
				
			||||||
	output         io.WriteCloser
 | 
						output         io.WriteCloser
 | 
				
			||||||
	reader         io.ReadCloser
 | 
						reader         io.ReadCloser
 | 
				
			||||||
 | 
						bufferedReader *bufio.Reader
 | 
				
			||||||
	done           chan error
 | 
						done           chan error
 | 
				
			||||||
	lastSha        *string
 | 
						lastSha        *string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -33,8 +34,6 @@ var shaLineRegex = regexp.MustCompile("^([a-z0-9]{40})")
 | 
				
			|||||||
func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
					func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
				
			||||||
	var blamePart *BlamePart
 | 
						var blamePart *BlamePart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reader := bufio.NewReader(r.reader)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r.lastSha != nil {
 | 
						if r.lastSha != nil {
 | 
				
			||||||
		blamePart = &BlamePart{*r.lastSha, make([]string, 0)}
 | 
							blamePart = &BlamePart{*r.lastSha, make([]string, 0)}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -44,7 +43,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
				
			|||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for err != io.EOF {
 | 
						for err != io.EOF {
 | 
				
			||||||
		line, isPrefix, err = reader.ReadLine()
 | 
							line, isPrefix, err = r.bufferedReader.ReadLine()
 | 
				
			||||||
		if err != nil && err != io.EOF {
 | 
							if err != nil && err != io.EOF {
 | 
				
			||||||
			return blamePart, err
 | 
								return blamePart, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -66,7 +65,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
				
			|||||||
				r.lastSha = &sha1
 | 
									r.lastSha = &sha1
 | 
				
			||||||
				// need to munch to end of line...
 | 
									// need to munch to end of line...
 | 
				
			||||||
				for isPrefix {
 | 
									for isPrefix {
 | 
				
			||||||
					_, isPrefix, err = reader.ReadLine()
 | 
										_, isPrefix, err = r.bufferedReader.ReadLine()
 | 
				
			||||||
					if err != nil && err != io.EOF {
 | 
										if err != nil && err != io.EOF {
 | 
				
			||||||
						return blamePart, err
 | 
											return blamePart, err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -81,7 +80,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// need to munch to end of line...
 | 
							// need to munch to end of line...
 | 
				
			||||||
		for isPrefix {
 | 
							for isPrefix {
 | 
				
			||||||
			_, isPrefix, err = reader.ReadLine()
 | 
								_, isPrefix, err = r.bufferedReader.ReadLine()
 | 
				
			||||||
			if err != nil && err != io.EOF {
 | 
								if err != nil && err != io.EOF {
 | 
				
			||||||
				return blamePart, err
 | 
									return blamePart, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -96,6 +95,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 | 
				
			|||||||
// Close BlameReader - don't run NextPart after invoking that
 | 
					// Close BlameReader - don't run NextPart after invoking that
 | 
				
			||||||
func (r *BlameReader) Close() error {
 | 
					func (r *BlameReader) Close() error {
 | 
				
			||||||
	err := <-r.done
 | 
						err := <-r.done
 | 
				
			||||||
 | 
						r.bufferedReader = nil
 | 
				
			||||||
	_ = r.reader.Close()
 | 
						_ = r.reader.Close()
 | 
				
			||||||
	_ = r.output.Close()
 | 
						_ = r.output.Close()
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
@@ -126,10 +126,13 @@ func CreateBlameReader(ctx context.Context, repoPath, commitID, file string) (*B
 | 
				
			|||||||
		done <- err
 | 
							done <- err
 | 
				
			||||||
	}(cmd, repoPath, stdout, done)
 | 
						}(cmd, repoPath, stdout, done)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bufferedReader := bufio.NewReader(reader)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &BlameReader{
 | 
						return &BlameReader{
 | 
				
			||||||
		cmd:            cmd,
 | 
							cmd:            cmd,
 | 
				
			||||||
		output:         stdout,
 | 
							output:         stdout,
 | 
				
			||||||
		reader:         reader,
 | 
							reader:         reader,
 | 
				
			||||||
 | 
							bufferedReader: bufferedReader,
 | 
				
			||||||
		done:           done,
 | 
							done:           done,
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ func TestReadingBlameOutput(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"f32b0a9dfd09a60f616f29158f772cedd89942d2",
 | 
								"f32b0a9dfd09a60f616f29158f772cedd89942d2",
 | 
				
			||||||
			[]string{},
 | 
								[]string{"", "Do not make any changes to this repo it is used for unit testing"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user