mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 19:06:18 +01:00 
			
		
		
		
	Mark parent directory as viewed when all files are viewed (#33958)
Fix #25644 --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		| @@ -1,86 +0,0 @@ | ||||
| import {mergeChildIfOnlyOneDir, pathListToTree, type File} from './filetree.ts'; | ||||
|  | ||||
| const emptyList: File[] = []; | ||||
| const singleFile = [{Name: 'file1'}] as File[]; | ||||
| const singleDir = [{Name: 'dir1/file1'}] as File[]; | ||||
| const nestedDir = [{Name: 'dir1/dir2/file1'}] as File[]; | ||||
| const multiplePathsDisjoint = [{Name: 'dir1/dir2/file1'}, {Name: 'dir3/file2'}] as File[]; | ||||
| const multiplePathsShared = [{Name: 'dir1/dir2/dir3/file1'}, {Name: 'dir1/file2'}] as File[]; | ||||
|  | ||||
| test('pathListToTree', () => { | ||||
|   expect(pathListToTree(emptyList)).toEqual([]); | ||||
|   expect(pathListToTree(singleFile)).toEqual([ | ||||
|     {isFile: true, name: 'file1', path: 'file1', file: {Name: 'file1'}}, | ||||
|   ]); | ||||
|   expect(pathListToTree(singleDir)).toEqual([ | ||||
|     {isFile: false, name: 'dir1', path: 'dir1', children: [ | ||||
|       {isFile: true, name: 'file1', path: 'dir1/file1', file: {Name: 'dir1/file1'}}, | ||||
|     ]}, | ||||
|   ]); | ||||
|   expect(pathListToTree(nestedDir)).toEqual([ | ||||
|     {isFile: false, name: 'dir1', path: 'dir1', children: [ | ||||
|       {isFile: false, name: 'dir2', path: 'dir1/dir2', children: [ | ||||
|         {isFile: true, name: 'file1', path: 'dir1/dir2/file1', file: {Name: 'dir1/dir2/file1'}}, | ||||
|       ]}, | ||||
|     ]}, | ||||
|   ]); | ||||
|   expect(pathListToTree(multiplePathsDisjoint)).toEqual([ | ||||
|     {isFile: false, name: 'dir1', path: 'dir1', children: [ | ||||
|       {isFile: false, name: 'dir2', path: 'dir1/dir2', children: [ | ||||
|         {isFile: true, name: 'file1', path: 'dir1/dir2/file1', file: {Name: 'dir1/dir2/file1'}}, | ||||
|       ]}, | ||||
|     ]}, | ||||
|     {isFile: false, name: 'dir3', path: 'dir3', children: [ | ||||
|       {isFile: true, name: 'file2', path: 'dir3/file2', file: {Name: 'dir3/file2'}}, | ||||
|     ]}, | ||||
|   ]); | ||||
|   expect(pathListToTree(multiplePathsShared)).toEqual([ | ||||
|     {isFile: false, name: 'dir1', path: 'dir1', children: [ | ||||
|       {isFile: false, name: 'dir2', path: 'dir1/dir2', children: [ | ||||
|         {isFile: false, name: 'dir3', path: 'dir1/dir2/dir3', children: [ | ||||
|           {isFile: true, name: 'file1', path: 'dir1/dir2/dir3/file1', file: {Name: 'dir1/dir2/dir3/file1'}}, | ||||
|         ]}, | ||||
|       ]}, | ||||
|       {isFile: true, name: 'file2', path: 'dir1/file2', file: {Name: 'dir1/file2'}}, | ||||
|     ]}, | ||||
|   ]); | ||||
| }); | ||||
|  | ||||
| const mergeChildWrapper = (testCase: File[]) => { | ||||
|   const tree = pathListToTree(testCase); | ||||
|   mergeChildIfOnlyOneDir(tree); | ||||
|   return tree; | ||||
| }; | ||||
|  | ||||
| test('mergeChildIfOnlyOneDir', () => { | ||||
|   expect(mergeChildWrapper(emptyList)).toEqual([]); | ||||
|   expect(mergeChildWrapper(singleFile)).toEqual([ | ||||
|     {isFile: true, name: 'file1', path: 'file1', file: {Name: 'file1'}}, | ||||
|   ]); | ||||
|   expect(mergeChildWrapper(singleDir)).toEqual([ | ||||
|     {isFile: false, name: 'dir1', path: 'dir1', children: [ | ||||
|       {isFile: true, name: 'file1', path: 'dir1/file1', file: {Name: 'dir1/file1'}}, | ||||
|     ]}, | ||||
|   ]); | ||||
|   expect(mergeChildWrapper(nestedDir)).toEqual([ | ||||
|     {isFile: false, name: 'dir1/dir2', path: 'dir1/dir2', children: [ | ||||
|       {isFile: true, name: 'file1', path: 'dir1/dir2/file1', file: {Name: 'dir1/dir2/file1'}}, | ||||
|     ]}, | ||||
|   ]); | ||||
|   expect(mergeChildWrapper(multiplePathsDisjoint)).toEqual([ | ||||
|     {isFile: false, name: 'dir1/dir2', path: 'dir1/dir2', children: [ | ||||
|       {isFile: true, name: 'file1', path: 'dir1/dir2/file1', file: {Name: 'dir1/dir2/file1'}}, | ||||
|     ]}, | ||||
|     {isFile: false, name: 'dir3', path: 'dir3', children: [ | ||||
|       {isFile: true, name: 'file2', path: 'dir3/file2', file: {Name: 'dir3/file2'}}, | ||||
|     ]}, | ||||
|   ]); | ||||
|   expect(mergeChildWrapper(multiplePathsShared)).toEqual([ | ||||
|     {isFile: false, name: 'dir1', path: 'dir1', children: [ | ||||
|       {isFile: false, name: 'dir2/dir3', path: 'dir1/dir2/dir3', children: [ | ||||
|         {isFile: true, name: 'file1', path: 'dir1/dir2/dir3/file1', file: {Name: 'dir1/dir2/dir3/file1'}}, | ||||
|       ]}, | ||||
|       {isFile: true, name: 'file2', path: 'dir1/file2', file: {Name: 'dir1/file2'}}, | ||||
|     ]}, | ||||
|   ]); | ||||
| }); | ||||
| @@ -1,85 +0,0 @@ | ||||
| import {dirname, basename} from '../utils.ts'; | ||||
|  | ||||
| export type FileStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'typechange'; | ||||
|  | ||||
| export type File = { | ||||
|   Name: string; | ||||
|   NameHash: string; | ||||
|   Status: FileStatus; | ||||
|   IsViewed: boolean; | ||||
|   IsSubmodule: boolean; | ||||
| } | ||||
|  | ||||
| type DirItem = { | ||||
|     isFile: false; | ||||
|     name: string; | ||||
|     path: string; | ||||
|  | ||||
|     children: Item[]; | ||||
| } | ||||
|  | ||||
| type FileItem = { | ||||
|     isFile: true; | ||||
|     name: string; | ||||
|     path: string; | ||||
|     file: File; | ||||
| } | ||||
|  | ||||
| export type Item = DirItem | FileItem; | ||||
|  | ||||
| export function pathListToTree(fileEntries: File[]): Item[] { | ||||
|   const pathToItem = new Map<string, DirItem>(); | ||||
|  | ||||
|     // init root node | ||||
|   const root: DirItem = {name: '', path: '', isFile: false, children: []}; | ||||
|   pathToItem.set('', root); | ||||
|  | ||||
|   for (const fileEntry of fileEntries) { | ||||
|     const [parentPath, fileName] = [dirname(fileEntry.Name), basename(fileEntry.Name)]; | ||||
|  | ||||
|     let parentItem = pathToItem.get(parentPath); | ||||
|     if (!parentItem) { | ||||
|       parentItem = constructParents(pathToItem, parentPath); | ||||
|     } | ||||
|  | ||||
|     const fileItem: FileItem = {name: fileName, path: fileEntry.Name, isFile: true, file: fileEntry}; | ||||
|  | ||||
|     parentItem.children.push(fileItem); | ||||
|   } | ||||
|  | ||||
|   return root.children; | ||||
| } | ||||
|  | ||||
| function constructParents(pathToItem: Map<string, DirItem>, dirPath: string): DirItem { | ||||
|   const [dirParentPath, dirName] = [dirname(dirPath), basename(dirPath)]; | ||||
|  | ||||
|   let parentItem = pathToItem.get(dirParentPath); | ||||
|   if (!parentItem) { | ||||
|     // if the parent node does not exist, create it | ||||
|     parentItem = constructParents(pathToItem, dirParentPath); | ||||
|   } | ||||
|  | ||||
|   const dirItem: DirItem = {name: dirName, path: dirPath, isFile: false, children: []}; | ||||
|   parentItem.children.push(dirItem); | ||||
|   pathToItem.set(dirPath, dirItem); | ||||
|  | ||||
|   return dirItem; | ||||
| } | ||||
|  | ||||
| export function mergeChildIfOnlyOneDir(nodes: Item[]): void { | ||||
|   for (const node of nodes) { | ||||
|     if (node.isFile) { | ||||
|       continue; | ||||
|     } | ||||
|     const dir = node as DirItem; | ||||
|  | ||||
|     mergeChildIfOnlyOneDir(dir.children); | ||||
|  | ||||
|     if (dir.children.length === 1 && dir.children[0].isFile === false) { | ||||
|       const child = dir.children[0]; | ||||
|       dir.name = `${dir.name}/${child.name}`; | ||||
|       dir.path = child.path; | ||||
|       dir.children = child.children; | ||||
|     } | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user