@@ -305,13 +305,21 @@ class AzureDevOpsService {
305
305
projectName
306
306
) ;
307
307
308
- // Get detailed content for each change (with size limits for safety)
309
- const MAX_FILE_SIZE = 100000 ; // Limit file size to 100KB for performance
308
+ // File size and content handling constants
309
+ const MAX_INLINE_FILE_SIZE = 500000 ; // Increased to 500KB for inline content
310
+ const MAX_CHUNK_SIZE = 100000 ; // 100KB chunks for larger files
311
+ const PREVIEW_SIZE = 10000 ; // 10KB preview for very large files
312
+
313
+ // Get detailed content for each change
310
314
const enhancedChanges = await Promise . all (
311
315
( changes . changeEntries || [ ] ) . map ( async ( change : any ) => {
312
316
const filePath = change . item ?. path || '' ;
313
317
let originalContent = null ;
314
318
let modifiedContent = null ;
319
+ let originalContentSize = 0 ;
320
+ let modifiedContentSize = 0 ;
321
+ let originalContentPreview = null ;
322
+ let modifiedContentPreview = null ;
315
323
316
324
// Skip folders or binary files
317
325
const isBinary = this . isBinaryFile ( filePath ) ;
@@ -322,21 +330,44 @@ class AzureDevOpsService {
322
330
// Get original content if the file wasn't newly added
323
331
if ( change . changeType !== 'add' && change . originalObjectId ) {
324
332
try {
325
- const originalItemContent = await this . gitClient . getItemContent (
333
+ // First get the item metadata to check file size
334
+ const originalItem = await this . gitClient . getItem (
326
335
repositoryId ,
327
336
filePath ,
328
337
projectName ,
329
- change . originalObjectId ,
330
- undefined ,
331
- true ,
332
- true
338
+ change . originalObjectId
333
339
) ;
334
340
335
- // Check if the content is too large
336
- if ( originalItemContent && originalItemContent . length < MAX_FILE_SIZE ) {
341
+ originalContentSize = originalItem ?. contentMetadata ?. contentLength || 0 ;
342
+
343
+ // For files within the inline limit, get full content
344
+ if ( originalContentSize <= MAX_INLINE_FILE_SIZE ) {
345
+ const originalItemContent = await this . gitClient . getItemContent (
346
+ repositoryId ,
347
+ filePath ,
348
+ projectName ,
349
+ change . originalObjectId ,
350
+ undefined ,
351
+ true ,
352
+ true
353
+ ) ;
354
+
337
355
originalContent = originalItemContent . toString ( 'utf8' ) ;
338
- } else {
339
- originalContent = '(File too large to display)' ;
356
+ }
357
+ // For large files, get a preview
358
+ else {
359
+ // Get just the beginning of the file for preview
360
+ const previewContent = await this . gitClient . getItemText (
361
+ repositoryId ,
362
+ filePath ,
363
+ projectName ,
364
+ change . originalObjectId ,
365
+ 0 , // Start at beginning
366
+ PREVIEW_SIZE // Get preview bytes
367
+ ) ;
368
+
369
+ originalContentPreview = previewContent ;
370
+ originalContent = `(File too large to display inline - ${ Math . round ( originalContentSize / 1024 ) } KB. Preview shown.)` ;
340
371
}
341
372
} catch ( error ) {
342
373
console . error ( `Error getting original content for ${ filePath } :` , error ) ;
@@ -347,21 +378,44 @@ class AzureDevOpsService {
347
378
// Get modified content if the file wasn't deleted
348
379
if ( change . changeType !== 'delete' && change . item . objectId ) {
349
380
try {
350
- const modifiedItemContent = await this . gitClient . getItemContent (
381
+ // First get the item metadata to check file size
382
+ const modifiedItem = await this . gitClient . getItem (
351
383
repositoryId ,
352
384
filePath ,
353
385
projectName ,
354
- change . item . objectId ,
355
- undefined ,
356
- true ,
357
- true
386
+ change . item . objectId
358
387
) ;
359
388
360
- // Check if the content is too large
361
- if ( modifiedItemContent && modifiedItemContent . length < MAX_FILE_SIZE ) {
389
+ modifiedContentSize = modifiedItem ?. contentMetadata ?. contentLength || 0 ;
390
+
391
+ // For files within the inline limit, get full content
392
+ if ( modifiedContentSize <= MAX_INLINE_FILE_SIZE ) {
393
+ const modifiedItemContent = await this . gitClient . getItemContent (
394
+ repositoryId ,
395
+ filePath ,
396
+ projectName ,
397
+ change . item . objectId ,
398
+ undefined ,
399
+ true ,
400
+ true
401
+ ) ;
402
+
362
403
modifiedContent = modifiedItemContent . toString ( 'utf8' ) ;
363
- } else {
364
- modifiedContent = '(File too large to display)' ;
404
+ }
405
+ // For large files, get a preview
406
+ else {
407
+ // Get just the beginning of the file for preview
408
+ const previewContent = await this . gitClient . getItemText (
409
+ repositoryId ,
410
+ filePath ,
411
+ projectName ,
412
+ change . item . objectId ,
413
+ 0 , // Start at beginning
414
+ PREVIEW_SIZE // Get preview bytes
415
+ ) ;
416
+
417
+ modifiedContentPreview = previewContent ;
418
+ modifiedContent = `(File too large to display inline - ${ Math . round ( modifiedContentSize / 1024 ) } KB. Preview shown.)` ;
365
419
}
366
420
} catch ( error ) {
367
421
console . error ( `Error getting modified content for ${ filePath } :` , error ) ;
@@ -378,6 +432,12 @@ class AzureDevOpsService {
378
432
...change ,
379
433
originalContent,
380
434
modifiedContent,
435
+ originalContentSize,
436
+ modifiedContentSize,
437
+ originalContentPreview,
438
+ modifiedContentPreview,
439
+ isBinary,
440
+ isFolder,
381
441
} as PullRequestChange ;
382
442
383
443
return enhancedChange ;
@@ -390,6 +450,60 @@ class AzureDevOpsService {
390
450
} ;
391
451
}
392
452
453
+ /**
454
+ * Get content for a specific file in a pull request by chunks
455
+ * This allows retrieving parts of large files that can't be displayed inline
456
+ */
457
+ async getPullRequestFileContent (
458
+ repositoryId : string ,
459
+ pullRequestId : number ,
460
+ filePath : string ,
461
+ objectId : string ,
462
+ startPosition : number ,
463
+ length : number ,
464
+ project ?: string
465
+ ) : Promise < { content : string ; size : number ; position : number ; length : number } > {
466
+ await this . initialize ( ) ;
467
+
468
+ if ( ! this . gitClient ) {
469
+ throw new Error ( 'Git client not initialized' ) ;
470
+ }
471
+
472
+ // Use the provided project or fall back to the default project
473
+ const projectName = project || this . defaultProject ;
474
+
475
+ if ( ! projectName ) {
476
+ throw new Error ( 'Project name is required' ) ;
477
+ }
478
+
479
+ try {
480
+ // Get metadata about the file to know its full size
481
+ const item = await this . gitClient . getItem ( repositoryId , filePath , projectName , objectId ) ;
482
+
483
+ const fileSize = item ?. contentMetadata ?. contentLength || 0 ;
484
+
485
+ // Get the specified chunk of content
486
+ const content = await this . gitClient . getItemText (
487
+ repositoryId ,
488
+ filePath ,
489
+ projectName ,
490
+ objectId ,
491
+ startPosition ,
492
+ length
493
+ ) ;
494
+
495
+ return {
496
+ content,
497
+ size : fileSize ,
498
+ position : startPosition ,
499
+ length : content . length ,
500
+ } ;
501
+ } catch ( error ) {
502
+ console . error ( `Error getting file content for ${ filePath } :` , error ) ;
503
+ throw new Error ( `Failed to retrieve content for file: ${ filePath } ` ) ;
504
+ }
505
+ }
506
+
393
507
/**
394
508
* Helper function to determine if a file is likely binary based on extension
395
509
*/
0 commit comments