@@ -12,6 +12,9 @@ const GENERATED_ATTRIBUTES = ['linguist-generated', 'gitlab-generated'];
1212const isGeneratedAttributeValue = ( value ) =>
1313 value !== 'unspecified' && value !== 'unset' && value !== 'false' ;
1414
15+ /** @param {string } value */
16+ const isNotGeneratedAttributeValue = ( value ) => value === 'unset' || value === 'false' ;
17+
1518/** @param {import('../core/types.ts').ReviewSource } source */
1619const getGeneratedAttributeSource = ( source ) =>
1720 source . type === 'commit'
@@ -25,17 +28,19 @@ const getGeneratedAttributeSource = (source) =>
2528 : undefined ;
2629
2730/** @param {Buffer } output */
28- const parseGeneratedAttributePaths = ( output ) => {
31+ const parseGeneratedAttributeStates = ( output ) => {
2932 const fields = output . toString ( 'utf8' ) . split ( '\0' ) ;
30- const generatedPaths = new Set ( ) ;
33+ const generatedStates = new Map ( ) ;
3134 for ( let index = 0 ; index + 2 < fields . length ; index += 3 ) {
3235 const path = fields [ index ] ;
3336 const value = fields [ index + 2 ] ;
3437 if ( path && isGeneratedAttributeValue ( value ) ) {
35- generatedPaths . add ( path ) ;
38+ generatedStates . set ( path , true ) ;
39+ } else if ( path && isNotGeneratedAttributeValue ( value ) && generatedStates . get ( path ) !== true ) {
40+ generatedStates . set ( path , false ) ;
3641 }
3742 }
38- return generatedPaths ;
43+ return generatedStates ;
3944} ;
4045
4146/**
@@ -44,8 +49,8 @@ const parseGeneratedAttributePaths = (output) => {
4449 * @param {ReadonlyArray<string> } options
4550 * @param {NodeJS.ProcessEnv } [env]
4651 */
47- const checkGeneratedAttributePaths = async ( repoRoot , paths , options , env ) =>
48- parseGeneratedAttributePaths (
52+ const checkGeneratedAttributeStates = async ( repoRoot , paths , options , env ) =>
53+ parseGeneratedAttributeStates (
4954 await gitBufferWithInput (
5055 repoRoot ,
5156 [ 'check-attr' , ...options , '-z' , '--stdin' , ...GENERATED_ATTRIBUTES ] ,
@@ -63,7 +68,7 @@ const checkGeneratedAttributePaths = async (repoRoot, paths, options, env) =>
6368 * @param {ReadonlyArray<string> } paths
6469 * @param {string } source
6570 */
66- const readGeneratedAttributePathsFromTree = async ( repoRoot , paths , source ) => {
71+ const readGeneratedAttributeStatesFromTree = async ( repoRoot , paths , source ) => {
6772 const temporaryDirectory = await mkdtemp ( join ( tmpdir ( ) , 'codiff-generated-files-' ) ) ;
6873 const env = {
6974 ...process . env ,
@@ -72,7 +77,7 @@ const readGeneratedAttributePathsFromTree = async (repoRoot, paths, source) => {
7277
7378 try {
7479 await gitBufferWithInput ( repoRoot , [ 'read-tree' , source ] , Buffer . alloc ( 0 ) , { env } ) ;
75- return await checkGeneratedAttributePaths ( repoRoot , paths , [ '--cached' ] , env ) ;
80+ return await checkGeneratedAttributeStates ( repoRoot , paths , [ '--cached' ] , env ) ;
7681 } finally {
7782 await rm ( temporaryDirectory , { force : true , recursive : true } ) ;
7883 }
@@ -83,49 +88,60 @@ const readGeneratedAttributePathsFromTree = async (repoRoot, paths, source) => {
8388 * @param {ReadonlyArray<string> } paths
8489 * @param {string | undefined } source
8590 */
86- const readGeneratedAttributePaths = async ( repoRoot , paths , source ) => {
91+ const readGeneratedAttributeStates = async ( repoRoot , paths , source ) => {
8792 if ( paths . length === 0 ) {
88- return new Set ( ) ;
93+ return new Map ( ) ;
8994 }
9095
9196 try {
92- return await checkGeneratedAttributePaths ( repoRoot , paths , source ? [ '--source' , source ] : [ ] ) ;
97+ return await checkGeneratedAttributeStates ( repoRoot , paths , source ? [ '--source' , source ] : [ ] ) ;
9398 } catch {
9499 if ( source ) {
95100 try {
96101 // Git before 2.40 rejects `--source`; use its historical-tree fallback.
97- return await readGeneratedAttributePathsFromTree ( repoRoot , paths , source ) ;
102+ return await readGeneratedAttributeStatesFromTree ( repoRoot , paths , source ) ;
98103 } catch {
99104 // Ignore invalid or unavailable historical sources.
100105 }
101106 }
102- return new Set ( ) ;
107+ return new Map ( ) ;
103108 }
104109} ;
105110
111+ /**
112+ * @param {import('../core/types.ts').RepositoryState } state
113+ * @param {ReadonlyMap<string, boolean> } generatedAttributeStates
114+ */
115+ const applyGeneratedAttributeStates = ( state , generatedAttributeStates ) => ( {
116+ ...state ,
117+ files : state . files . map ( ( file ) => {
118+ const attributeState = generatedAttributeStates . get ( file . path ) ;
119+ if ( attributeState != null ) {
120+ return file . generated === attributeState ? file : { ...file , generated : attributeState } ;
121+ }
122+ if ( file . generated != null ) {
123+ return file ;
124+ }
125+ return isGeneratedWalkthroughPath ( file . path ) ? { ...file , generated : true } : file ;
126+ } ) ,
127+ } ) ;
128+
106129/** @param {import('../core/types.ts').RepositoryState } state */
107- const annotateGeneratedFiles = async ( state ) => {
108- const generatedAttributePaths = await readGeneratedAttributePaths (
109- state . root ,
110- state . files . map ( ( file ) => file . path ) ,
111- getGeneratedAttributeSource ( state . source ) ,
112- ) ;
113- return {
114- ...state ,
115- files : state . files . map ( ( file ) =>
116- file . generated ||
117- generatedAttributePaths . has ( file . path ) ||
118- isGeneratedWalkthroughPath ( file . path )
119- ? { ...file , generated : true }
120- : file ,
130+ const annotateGeneratedFiles = async ( state ) =>
131+ applyGeneratedAttributeStates (
132+ state ,
133+ await readGeneratedAttributeStates (
134+ state . root ,
135+ state . files . map ( ( file ) => file . path ) ,
136+ getGeneratedAttributeSource ( state . source ) ,
121137 ) ,
122- } ;
123- } ;
138+ ) ;
124139
125140module . exports = {
126141 GENERATED_ATTRIBUTES ,
127142 annotateGeneratedFiles,
143+ applyGeneratedAttributeStates,
128144 getGeneratedAttributeSource,
129145 isGeneratedAttributeValue,
130- readGeneratedAttributePaths ,
146+ readGeneratedAttributeStates ,
131147} ;
0 commit comments