From 3be6a1dc1504ccc4e27432b25a6f27052fdfeb3c Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Mon, 9 Dec 2024 06:23:59 +0000 Subject: [PATCH 1/9] Improve implementation of diff-file-tree --- services/gitdiff/gitdiff.go | 72 +++++++++++++++++++++++ templates/repo/diff/box.tmpl | 10 +--- templates/repo/diff/file_tree.tmpl | 12 ++++ templates/repo/diff/file_tree_item.tmpl | 32 ++++++++++ web_src/css/repo.css | 56 +++++++++++++++++- web_src/js/features/repo-diff-filetree.ts | 51 +++++++++++++++- web_src/js/features/repo-diff.ts | 4 +- 7 files changed, 223 insertions(+), 14 deletions(-) create mode 100644 templates/repo/diff/file_tree.tmpl create mode 100644 templates/repo/diff/file_tree_item.tmpl diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index bb1722039e19d..8e349bf0b292d 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -448,12 +448,20 @@ func getCommitFileLineCount(commit *git.Commit, filePath string) int { return lineCount } +type FileTreeNode struct { + IsFile bool + Name string + File *DiffFile + Children []*FileTreeNode +} + // Diff represents a difference between two git trees. type Diff struct { Start, End string NumFiles int TotalAddition, TotalDeletion int Files []*DiffFile + FileTree []*FileTreeNode IsIncomplete bool NumViewedFiles int // user-specific } @@ -1212,6 +1220,8 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi } } + diff.FileTree = buildTree(diff.Files) + if opts.FileOnly { return diff, nil } @@ -1384,3 +1394,65 @@ func GetWhitespaceFlag(whitespaceBehavior string) git.TrustedCmdArgs { log.Warn("unknown whitespace behavior: %q, default to 'show-all'", whitespaceBehavior) return nil } + +func buildTree(files []*DiffFile) []*FileTreeNode { + result := make(map[string]*FileTreeNode) + for _, file := range files { + splits := strings.Split(file.Name, "/") + currentNode := &FileTreeNode{Name: splits[0], IsFile: false} + if _, exists := result[splits[0]]; !exists { + result[splits[0]] = currentNode + } else { + currentNode = result[splits[0]] + } + + parent := currentNode + for _, split := range splits[1:] { + found := false + for _, child := range parent.Children { + if child.Name == split { + parent = child + found = true + break + } + } + if !found { + newNode := &FileTreeNode{Name: split, IsFile: false} + parent.Children = append(parent.Children, newNode) + parent = newNode + } + } + + lastNode := parent + lastNode.IsFile = true + lastNode.File = file + } + + var roots []*FileTreeNode + for _, node := range result { + if len(node.Children) > 0 { + mergedNode := mergeSingleChildDirs(node) + roots = append(roots, mergedNode) + } + } + return roots +} + +func mergeSingleChildDirs(node *FileTreeNode) *FileTreeNode { + if len(node.Children) == 1 && !node.Children[0].IsFile { + merged := &FileTreeNode{ + Name: fmt.Sprintf("%s/%s", node.Name, node.Children[0].Name), + Children: node.Children[0].Children, + IsFile: node.Children[0].IsFile, + File: node.Children[0].File, + } + if merged.File != nil { + merged.IsFile = true + } + return merged + } + for _, child := range node.Children { + mergeSingleChildDirs(child) + } + return node +} diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index 0f1458bfbfd22..b752b26812e48 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -61,35 +61,29 @@ {{end}}
{{end}}
{{if $showFileTree}} -
+ {{template "repo/diff/file_tree" dict "Files" .Diff.FileTree "IsIncomplete" .Diff.IsIncomplete "LoadMoreLink" "?skip-to={{.Diff.End}}&file-only=true"}} @@ -228,7 +222,7 @@

{{ctx.Locale.Tr "repo.diff.too_many_files"}} - {{ctx.Locale.Tr "repo.diff.show_more"}} + {{ctx.Locale.Tr "repo.diff.show_more"}}

{{end}} diff --git a/templates/repo/diff/file_tree.tmpl b/templates/repo/diff/file_tree.tmpl new file mode 100644 index 0000000000000..ba72b4f4eab4e --- /dev/null +++ b/templates/repo/diff/file_tree.tmpl @@ -0,0 +1,12 @@ +
+
+ {{range .Files}} + {{template "repo/diff/file_tree_item" .}} + {{end}} +
+ {{if .IsIncomplete}} + + {{end}} +
diff --git a/templates/repo/diff/file_tree_item.tmpl b/templates/repo/diff/file_tree_item.tmpl new file mode 100644 index 0000000000000..c0755f5fedf75 --- /dev/null +++ b/templates/repo/diff/file_tree_item.tmpl @@ -0,0 +1,32 @@ +{{if .IsFile}} + + + {{svg "octicon-file"}} + {{ .Name }} + {{if eq .File.Type 1}} + {{svg "octicon-diff-added" 16 "text green"}} + {{else if eq .File.Type 2}} + {{svg "octicon-diff-modified" 16 "text yellow"}} + {{else if eq .File.Type 3}} + {{svg "octicon-diff-removed" 16 "text red"}} + {{else if eq .File.Type 4}} + {{svg "octicon-diff-renamed" 16 "text teal"}} + {{else if eq .File.Type 5}} + {{svg "octicon-diff-renamed" 16 "text green"}} + {{end}} + +{{else}} +
+ + {{svg "octicon-chevron-down"}} + {{svg "octicon-file-directory-open-fill" 16 "text primary"}} + {{ .Name }} +
+{{end}} +{{if and .Children (gt (len .Children) 0)}} +
+ {{range .Children}} + {{template "repo/diff/file_tree_item" .}} + {{end}} +
+{{end}} diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 14bdc434749ea..3efc0d4e730b4 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -2377,7 +2377,7 @@ tbody.commit-list { gap: 8px; } -#diff-file-tree { +.file-tree { flex: 0 0 20%; max-width: 380px; line-height: inherit; @@ -2389,6 +2389,60 @@ tbody.commit-list { overflow-y: auto; } +.file-tree .file-tree-items { + display: flex; + flex-direction: column; + gap: 1px; + margin-right: .5rem; +} + +.file-tree .file-tree-items a, a:hover { + text-decoration: none; + color: var(--color-text); +} + +.file-tree .file-tree-items .sub-items { + display: flex; + flex-direction: column; + gap: 1px; + margin-left: 13px; + border-left: 1px solid var(--color-secondary); +} + +.file-tree .file-tree-items .sub-items .item-file { + padding-left: 18px; +} + +.file-tree .file-tree-items .item-file.selected { + color: var(--color-text); + background: var(--color-active); + border-radius: 4px; +} + +.file-tree .file-tree-items .item-file.viewed { + color: var(--color-text-light-3); +} + +.file-tree .file-tree-items .item-directory { + user-select: none; +} + +.file-tree .file-tree-items .item-file, +.file-tree .file-tree-items .item-directory { + display: flex; + align-items: center; + gap: 0.25em; + padding: 6px; +} + +.file-tree .file-tree-items .item-file:hover, +.file-tree .file-tree-items .item-directory:hover { + color: var(--color-text); + background: var(--color-hover); + border-radius: 4px; + cursor: pointer; +} + .ui.message.unicode-escape-prompt { margin-bottom: 0; border-radius: 0; diff --git a/web_src/js/features/repo-diff-filetree.ts b/web_src/js/features/repo-diff-filetree.ts index bc275a90f6ab3..191d133955bf8 100644 --- a/web_src/js/features/repo-diff-filetree.ts +++ b/web_src/js/features/repo-diff-filetree.ts @@ -1,13 +1,58 @@ import {createApp} from 'vue'; -import DiffFileTree from '../components/DiffFileTree.vue'; +import {toggleElem} from '../utils/dom.ts'; +import {diffTreeStore} from '../modules/stores.ts'; +import {setFileFolding} from './file-fold.ts'; import DiffFileList from '../components/DiffFileList.vue'; +const LOCAL_STORAGE_KEY = 'diff_file_tree_visible'; + +function hashChangeListener() { + for (const el of document.querySelectorAll('.file-tree-items .item-file')) { + el.classList.toggle('selected', el.hash === `${window.location.hash}`); + } + expandSelectedFile(window.location.hash); +} + +function expandSelectedFile(selectedItem) { + // expand file if the selected file is folded + if (selectedItem) { + const box = document.querySelector(selectedItem); + const folded = box?.getAttribute('data-folded') === 'true'; + if (folded) setFileFolding(box, box.querySelector('.fold-file'), false); + } +} + +function updateState(visible) { + const btn = document.querySelector('.diff-toggle-file-tree-button'); + const [toShow, toHide] = btn.querySelectorAll('.icon'); + const tree = document.querySelector('#diff-file-tree'); + const newTooltip = btn.getAttribute(visible ? 'data-hide-text' : 'data-show-text'); + btn.setAttribute('data-tooltip-content', newTooltip); + toggleElem(tree, visible); + toggleElem(toShow, !visible); + toggleElem(toHide, visible); +} + export function initDiffFileTree() { const el = document.querySelector('#diff-file-tree'); if (!el) return; - const fileTreeView = createApp(DiffFileTree); - fileTreeView.mount(el); + const store = diffTreeStore(); + store.fileTreeIsVisible = localStorage.getItem(LOCAL_STORAGE_KEY) !== 'false'; + document.querySelector('.diff-toggle-file-tree-button').addEventListener('click', () => { + store.fileTreeIsVisible = !store.fileTreeIsVisible; + localStorage.setItem(LOCAL_STORAGE_KEY, store.fileTreeIsVisible); + updateState(store.fileTreeIsVisible); + }); + + hashChangeListener(); + window.addEventListener('hashchange', hashChangeListener); + + for (const el of document.querySelectorAll('.file-tree-items .item-directory')) { + el.addEventListener('click', () => { + toggleElem(el.nextElementSibling); + }); + } } export function initDiffFileList() { diff --git a/web_src/js/features/repo-diff.ts b/web_src/js/features/repo-diff.ts index 58e0d880922dd..3c83306900da7 100644 --- a/web_src/js/features/repo-diff.ts +++ b/web_src/js/features/repo-diff.ts @@ -166,7 +166,7 @@ function onShowMoreFiles() { } export async function loadMoreFiles(url) { - const target = document.querySelector('a#diff-show-more-files'); + const target = document.querySelector('a.diff-show-more-files'); if (target?.classList.contains('disabled') || pageData.diffFileInfo.isLoadingNewData) { return; } @@ -195,7 +195,7 @@ export async function loadMoreFiles(url) { } function initRepoDiffShowMore() { - $(document).on('click', 'a#diff-show-more-files', (e) => { + $(document).on('click', 'a.diff-show-more-files', (e) => { e.preventDefault(); const linkLoadMore = e.target.getAttribute('data-href'); From 5cf8d37eb1a4b19efdff175e3434b2d9fdae3337 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Mon, 9 Dec 2024 06:36:15 +0000 Subject: [PATCH 2/9] fix lint-error --- templates/repo/diff/file_tree.tmpl | 4 ++-- templates/repo/diff/file_tree_item.tmpl | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/templates/repo/diff/file_tree.tmpl b/templates/repo/diff/file_tree.tmpl index ba72b4f4eab4e..b5ca34e35f9c3 100644 --- a/templates/repo/diff/file_tree.tmpl +++ b/templates/repo/diff/file_tree.tmpl @@ -1,9 +1,9 @@
{{range .Files}} - {{template "repo/diff/file_tree_item" .}} + {{template "repo/diff/file_tree_item" .}} {{end}} -
+
{{if .IsIncomplete}}
{{ctx.Locale.Tr "repo.diff.show_more"}} diff --git a/templates/repo/diff/file_tree_item.tmpl b/templates/repo/diff/file_tree_item.tmpl index c0755f5fedf75..33bb3b9268cae 100644 --- a/templates/repo/diff/file_tree_item.tmpl +++ b/templates/repo/diff/file_tree_item.tmpl @@ -17,16 +17,16 @@ {{else}}
- + {{svg "octicon-chevron-down"}} {{svg "octicon-file-directory-open-fill" 16 "text primary"}} - {{ .Name }} -
+ {{ .Name }} +
{{end}} {{if and .Children (gt (len .Children) 0)}}
{{range .Children}} - {{template "repo/diff/file_tree_item" .}} + {{template "repo/diff/file_tree_item" .}} {{end}}
{{end}} From 08def8873ec99fc73f88a6d4fe5a10e44b312fa0 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Mon, 9 Dec 2024 06:45:58 +0000 Subject: [PATCH 3/9] fix --- templates/repo/diff/box.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index b752b26812e48..0be1a09ff2b5d 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -83,7 +83,7 @@ {{end}}
{{if $showFileTree}} - {{template "repo/diff/file_tree" dict "Files" .Diff.FileTree "IsIncomplete" .Diff.IsIncomplete "LoadMoreLink" "?skip-to={{.Diff.End}}&file-only=true"}} + {{template "repo/diff/file_tree" dict "Files" .Diff.FileTree "IsIncomplete" .Diff.IsIncomplete "LoadMoreLink" (printf "?skip-to=%s&file-only=true" .Diff.End)}} From 90324327acbdf406bf68d2e4f334dfb208f9b49d Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Mon, 9 Dec 2024 06:52:22 +0000 Subject: [PATCH 4/9] fix --- templates/repo/diff/file_tree.tmpl | 2 +- templates/repo/diff/file_tree_item.tmpl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/repo/diff/file_tree.tmpl b/templates/repo/diff/file_tree.tmpl index b5ca34e35f9c3..c0cee3164813b 100644 --- a/templates/repo/diff/file_tree.tmpl +++ b/templates/repo/diff/file_tree.tmpl @@ -6,7 +6,7 @@
{{if .IsIncomplete}} {{end}}
diff --git a/templates/repo/diff/file_tree_item.tmpl b/templates/repo/diff/file_tree_item.tmpl index 33bb3b9268cae..311360a9e28e3 100644 --- a/templates/repo/diff/file_tree_item.tmpl +++ b/templates/repo/diff/file_tree_item.tmpl @@ -1,8 +1,8 @@ {{if .IsFile}} - + {{svg "octicon-file"}} - {{ .Name }} + {{.Name}} {{if eq .File.Type 1}} {{svg "octicon-diff-added" 16 "text green"}} {{else if eq .File.Type 2}} @@ -16,11 +16,11 @@ {{end}} {{else}} -
+
{{svg "octicon-chevron-down"}} {{svg "octicon-file-directory-open-fill" 16 "text primary"}} - {{ .Name }} + {{.Name}}
{{end}} {{if and .Children (gt (len .Children) 0)}} From f5d22f0ee0ba06825c76bdf8df0b599db2898b41 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Tue, 10 Dec 2024 01:16:42 +0000 Subject: [PATCH 5/9] fix --- templates/repo/diff/file_tree_item.tmpl | 4 +++- web_src/js/features/repo-diff-filetree.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/templates/repo/diff/file_tree_item.tmpl b/templates/repo/diff/file_tree_item.tmpl index 311360a9e28e3..837082461fd48 100644 --- a/templates/repo/diff/file_tree_item.tmpl +++ b/templates/repo/diff/file_tree_item.tmpl @@ -18,7 +18,9 @@ {{else}}
- {{svg "octicon-chevron-down"}} + {{svg "octicon-chevron-right" 16 "tw-hidden"}} + {{svg "octicon-chevron-down" 16}} + {{svg "octicon-file-directory-fill" 16 "text primary tw-hidden"}} {{svg "octicon-file-directory-open-fill" 16 "text primary"}} {{.Name}}
diff --git a/web_src/js/features/repo-diff-filetree.ts b/web_src/js/features/repo-diff-filetree.ts index 191d133955bf8..4cb4bf2ceabe5 100644 --- a/web_src/js/features/repo-diff-filetree.ts +++ b/web_src/js/features/repo-diff-filetree.ts @@ -51,6 +51,7 @@ export function initDiffFileTree() { for (const el of document.querySelectorAll('.file-tree-items .item-directory')) { el.addEventListener('click', () => { toggleElem(el.nextElementSibling); + toggleElem(el.querySelectorAll('.svg.octicon-chevron-right, .svg.octicon-chevron-down, .svg.octicon-file-directory-fill, .svg.octicon-file-directory-open-fill')); }); } } From 50b8c444ec5da59fbb2e8529ac9366b3452902ab Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Tue, 10 Dec 2024 03:45:16 +0000 Subject: [PATCH 6/9] fix --- services/gitdiff/gitdiff.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 8e349bf0b292d..e644aec5b1fcb 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -1433,6 +1433,8 @@ func buildTree(files []*DiffFile) []*FileTreeNode { if len(node.Children) > 0 { mergedNode := mergeSingleChildDirs(node) roots = append(roots, mergedNode) + } else { + roots = append(roots, node) } } return roots @@ -1446,13 +1448,10 @@ func mergeSingleChildDirs(node *FileTreeNode) *FileTreeNode { IsFile: node.Children[0].IsFile, File: node.Children[0].File, } - if merged.File != nil { - merged.IsFile = true - } - return merged + return mergeSingleChildDirs(merged) } - for _, child := range node.Children { - mergeSingleChildDirs(child) + for i, child := range node.Children { + node.Children[i] = mergeSingleChildDirs(child) } return node } From c387ea4403b73458951dd3f03bcb36253a046f8a Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Tue, 10 Dec 2024 05:39:18 +0000 Subject: [PATCH 7/9] fixed sort --- services/gitdiff/gitdiff.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index e644aec5b1fcb..dacb3fff256c3 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -1432,11 +1432,13 @@ func buildTree(files []*DiffFile) []*FileTreeNode { for _, node := range result { if len(node.Children) > 0 { mergedNode := mergeSingleChildDirs(node) + sortChildren(mergedNode) roots = append(roots, mergedNode) } else { roots = append(roots, node) } } + sortChildren(&FileTreeNode{Children: roots}) return roots } @@ -1455,3 +1457,15 @@ func mergeSingleChildDirs(node *FileTreeNode) *FileTreeNode { } return node } + +func sortChildren(node *FileTreeNode) { + sort.Slice(node.Children, func(i, j int) bool { + if node.Children[i].IsFile == node.Children[j].IsFile { + return node.Children[i].Name < node.Children[j].Name + } + return !node.Children[i].IsFile + }) + for _, child := range node.Children { + sortChildren(child) + } +} From ec05be0c5c774e0ef97e7409f582a4f04f469129 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Tue, 10 Dec 2024 06:29:18 +0000 Subject: [PATCH 8/9] add tests --- services/gitdiff/gitdiff_test.go | 188 +++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index adcac355a7bb4..fbeb26d540691 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -668,3 +668,191 @@ func TestNoCrashes(t *testing.T) { ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") } } + +func TestBuildTree(t *testing.T) { + tests := []struct { + name string + input []*DiffFile + expected []*FileTreeNode + }{ + { + name: "Test case 1", + input: []*DiffFile{ + {Name: "2/2", NameHash: "23b3d60a69a4b1bacb1a3b9ced0a8ac609efbf61"}, + {Name: "test1", NameHash: "b444ac06613fc8d63795be9ad0beaf55011936ac"}, + }, + expected: []*FileTreeNode{ + { + Name: "2", + IsFile: false, + Children: []*FileTreeNode{ + { + Name: "2", + IsFile: true, + File: &DiffFile{ + Name: "2/2", + NameHash: "23b3d60a69a4b1bacb1a3b9ced0a8ac609efbf61", + }, + }, + }, + }, + { + Name: "test1", + IsFile: true, + File: &DiffFile{ + Name: "test1", + NameHash: "b444ac06613fc8d63795be9ad0beaf55011936ac", + }, + }, + }, + }, + { + name: "Test case 2", + input: []*DiffFile{ + {Name: "a/b/c", NameHash: "hash1"}, + {Name: "a/b/d", NameHash: "hash2"}, + {Name: "a/e", NameHash: "hash3"}, + {Name: "f", NameHash: "hash4"}, + }, + expected: []*FileTreeNode{ + { + Name: "a", + IsFile: false, + Children: []*FileTreeNode{ + { + Name: "b", + IsFile: false, + Children: []*FileTreeNode{ + { + Name: "c", + IsFile: true, + File: &DiffFile{ + Name: "a/b/c", + NameHash: "hash1", + }, + }, + { + Name: "d", + IsFile: true, + File: &DiffFile{ + Name: "a/b/d", + NameHash: "hash2", + }, + }, + }, + }, + { + Name: "e", + IsFile: true, + File: &DiffFile{ + Name: "a/e", + NameHash: "hash3", + }, + }, + }, + }, + { + Name: "f", + IsFile: true, + File: &DiffFile{ + Name: "f", + NameHash: "hash4", + }, + }, + }, + }, + { + name: "Test case 3", + input: []*DiffFile{ + {Name: "dir1/file1", NameHash: "hash1"}, + {Name: "dir1/file2", NameHash: "hash2"}, + {Name: "dir2/file3", NameHash: "hash3"}, + {Name: "dir2/file4", NameHash: "hash4"}, + {Name: "file5", NameHash: "hash5"}, + }, + expected: []*FileTreeNode{ + { + Name: "dir1", + IsFile: false, + Children: []*FileTreeNode{ + { + Name: "file1", + IsFile: true, + File: &DiffFile{ + Name: "dir1/file1", + NameHash: "hash1", + }, + }, + { + Name: "file2", + IsFile: true, + File: &DiffFile{ + Name: "dir1/file2", + NameHash: "hash2", + }, + }, + }, + }, + { + Name: "dir2", + IsFile: false, + Children: []*FileTreeNode{ + { + Name: "file3", + IsFile: true, + File: &DiffFile{ + Name: "dir2/file3", + NameHash: "hash3", + }, + }, + { + Name: "file4", + IsFile: true, + File: &DiffFile{ + Name: "dir2/file4", + NameHash: "hash4", + }, + }, + }, + }, + { + Name: "file5", + IsFile: true, + File: &DiffFile{ + Name: "file5", + NameHash: "hash5", + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := buildTree(tt.input) + if !compareFileTreeNodes(result, tt.expected) { + t.Errorf("Expected %v, but got %v", tt.expected, result) + } + }) + } +} + +func compareFileTreeNodes(a, b []*FileTreeNode) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i].Name != b[i].Name || a[i].IsFile != b[i].IsFile { + return false + } + if a[i].IsFile && b[i].IsFile { + if a[i].File.Name != b[i].File.Name || a[i].File.NameHash != b[i].File.NameHash { + return false + } + } + if !compareFileTreeNodes(a[i].Children, b[i].Children) { + return false + } + } + return true +} From edb932cef963b437080c4bea16f252767320c3c7 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Tue, 10 Dec 2024 06:40:02 +0000 Subject: [PATCH 9/9] fix --- services/gitdiff/gitdiff_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index fbeb26d540691..d9af23f6a9e02 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -678,8 +678,8 @@ func TestBuildTree(t *testing.T) { { name: "Test case 1", input: []*DiffFile{ - {Name: "2/2", NameHash: "23b3d60a69a4b1bacb1a3b9ced0a8ac609efbf61"}, {Name: "test1", NameHash: "b444ac06613fc8d63795be9ad0beaf55011936ac"}, + {Name: "2/2", NameHash: "23b3d60a69a4b1bacb1a3b9ced0a8ac609efbf61"}, }, expected: []*FileTreeNode{ { @@ -709,9 +709,9 @@ func TestBuildTree(t *testing.T) { { name: "Test case 2", input: []*DiffFile{ - {Name: "a/b/c", NameHash: "hash1"}, {Name: "a/b/d", NameHash: "hash2"}, {Name: "a/e", NameHash: "hash3"}, + {Name: "a/b/c", NameHash: "hash1"}, {Name: "f", NameHash: "hash4"}, }, expected: []*FileTreeNode{ @@ -764,10 +764,10 @@ func TestBuildTree(t *testing.T) { { name: "Test case 3", input: []*DiffFile{ + {Name: "dir2/file4", NameHash: "hash4"}, {Name: "dir1/file1", NameHash: "hash1"}, - {Name: "dir1/file2", NameHash: "hash2"}, {Name: "dir2/file3", NameHash: "hash3"}, - {Name: "dir2/file4", NameHash: "hash4"}, + {Name: "dir1/file2", NameHash: "hash2"}, {Name: "file5", NameHash: "hash5"}, }, expected: []*FileTreeNode{