diff --git a/README.md b/README.md index f331488..0faa361 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Code Ownership & Review Assignment Tool - GitHub CODEOWNERS but better [![Go Report Card](https://goreportcard.com/badge/github.com/multimediallc/codeowners-plus)](https://goreportcard.com/report/github.com/multimediallc/codeowners-plus?kill_cache=1) [![Tests](https://github.com/multimediallc/codeowners-plus/actions/workflows/go.yml/badge.svg)](https://github.com/multimediallc/codeowners-plus/actions/workflows/go.yml) -![Coverage](https://img.shields.io/badge/Coverage-81.6%25-brightgreen) +![Coverage](https://img.shields.io/badge/Coverage-81.7%25-brightgreen) [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) diff --git a/internal/git/diff.go b/internal/git/diff.go index ee51feb..efc2488 100644 --- a/internal/git/diff.go +++ b/internal/git/diff.go @@ -111,13 +111,23 @@ type changesSinceContext struct { olderDiff []*diff.FileDiff } +func diffToFilename(d *diff.FileDiff) string { + if d.NewName == "/dev/null" { + // For deleted files, NewName is "/dev/null", so use OrigName instead + return d.OrigName[2:] + } + return d.NewName[2:] +} + // Parse the diff output to get the file names and hunks func toDiffFiles(fileDiffs []*diff.FileDiff) ([]codeowners.DiffFile, error) { diffFiles := make([]codeowners.DiffFile, 0, len(fileDiffs)) for _, d := range fileDiffs { + fileName := diffToFilename(d) + newDiffFile := codeowners.DiffFile{ - FileName: d.NewName[2:], + FileName: fileName, Hunks: make([]codeowners.HunkRange, 0, len(d.Hunks)), } for _, hunk := range d.Hunks { @@ -147,8 +157,10 @@ func changesSince(context changesSinceContext) ([]codeowners.DiffFile, error) { diffFiles := make([]codeowners.DiffFile, 0, len(context.newerDiff)) for _, d := range context.newerDiff { + fileName := diffToFilename(d) + newDiffFile := codeowners.DiffFile{ - FileName: d.NewName[2:], + FileName: fileName, Hunks: make([]codeowners.HunkRange, 0, len(d.Hunks)), } for _, hunk := range d.Hunks { @@ -177,8 +189,10 @@ func getGitDiff(data DiffContext, executor gitCommandExecutor) ([]*diff.FileDiff return nil, err } gitDiff = slices.DeleteFunc(gitDiff, func(d *diff.FileDiff) bool { + fileName := diffToFilename(d) + for _, dir := range data.IgnoreDirs { - if strings.HasPrefix(d.NewName[2:], dir) { + if strings.HasPrefix(fileName, dir) { return true } } diff --git a/internal/git/diff_test.go b/internal/git/diff_test.go index e52999d..ca5df80 100644 --- a/internal/git/diff_test.go +++ b/internal/git/diff_test.go @@ -110,6 +110,33 @@ func TestNewDiff(t *testing.T) { "file2.go": 1, }, }, + { + name: "ignore deleted files in ignored directories", + context: DiffContext{ + Base: "main", + Head: "feature", + Dir: ".", + IgnoreDirs: []string{"ignored/"}, + }, + mockOutput: `diff --git a/file1.go b/file1.go +index abc..def 100644 +--- a/file1.go ++++ b/file1.go +@@ -10,0 +11 @@ func Example() { ++ fmt.Println("New line") +diff --git a/ignored/deleted.go b/dev/null +deleted file mode 100644 +index ghi..0000000 +--- a/ignored/deleted.go ++++ /dev/null +@@ -1 +0,0 @@ +-content`, + expectedErr: false, + expectedFiles: 1, + expectedHunks: map[string]int{ + "file1.go": 1, + }, + }, } for _, tc := range tt { @@ -389,6 +416,94 @@ func TestToDiffFiles(t *testing.T) { }, }, }, + { + name: "deleted file", + fileDiffs: []*diff.FileDiff{ + { + OrigName: "a/deleted.go", + NewName: "/dev/null", + Hunks: []*diff.Hunk{ + { + NewStartLine: 0, + NewLines: 0, + }, + }, + }, + }, + expected: []codeowners.DiffFile{ + { + FileName: "deleted.go", + Hunks: []codeowners.HunkRange{ + { + Start: 0, + End: -1, + }, + }, + }, + }, + }, + { + name: "mixed: added, modified, and deleted files", + fileDiffs: []*diff.FileDiff{ + { + NewName: "b/added.go", + Hunks: []*diff.Hunk{ + { + NewStartLine: 1, + NewLines: 5, + }, + }, + }, + { + NewName: "b/modified.go", + Hunks: []*diff.Hunk{ + { + NewStartLine: 10, + NewLines: 2, + }, + }, + }, + { + OrigName: "a/deleted.go", + NewName: "/dev/null", + Hunks: []*diff.Hunk{ + { + NewStartLine: 0, + NewLines: 0, + }, + }, + }, + }, + expected: []codeowners.DiffFile{ + { + FileName: "added.go", + Hunks: []codeowners.HunkRange{ + { + Start: 1, + End: 5, + }, + }, + }, + { + FileName: "modified.go", + Hunks: []codeowners.HunkRange{ + { + Start: 10, + End: 11, + }, + }, + }, + { + FileName: "deleted.go", + Hunks: []codeowners.HunkRange{ + { + Start: 0, + End: -1, + }, + }, + }, + }, + }, } for _, tc := range tt {