@@ -516,7 +516,7 @@ export const prepareUploadArtifacts = (
516516 return { uploadEntries, manifestFiles }
517517}
518518
519- type GitTreeChange = {
519+ export type GitTreeChange = {
520520 readonly path : string
521521 readonly mode : "100644"
522522 readonly type : "blob"
@@ -533,25 +533,6 @@ const buildFileMapFromTreeEntries = (entries: ReadonlyArray<TreeEntry>): Map<str
533533 return fileMap
534534}
535535
536- export const removeSnapshotTreeEntries = (
537- entries : ReadonlyArray < TreeEntry > ,
538- snapshotRef : string
539- ) : ReadonlyArray < TreeEntry > => {
540- const snapshotPrefix = `${ snapshotRef } /`
541- return entries . filter ( ( entry ) => entry . path !== snapshotRef && ! entry . path . startsWith ( snapshotPrefix ) )
542- }
543-
544- export const buildSnapshotDeleteTreeEntries = (
545- entries : ReadonlyArray < TreeEntry > ,
546- snapshotRef : string ,
547- desiredPaths : ReadonlySet < string >
548- ) : ReadonlyArray < GitTreeChange > => {
549- const snapshotPrefix = `${ snapshotRef } /`
550- return entries
551- . filter ( ( entry ) => entry . type !== "tree" && entry . path . startsWith ( snapshotPrefix ) && ! desiredPaths . has ( entry . path ) )
552- . map ( ( entry ) => ( { path : entry . path , mode : "100644" , type : "blob" , sha : null } ) )
553- }
554-
555536const createGitBlob = ( repoFullName : string , entry : UploadEntry , ghEnv : GhEnv ) : string => {
556537 const content = fs . readFileSync ( entry . sourcePath )
557538 const result = ensureSuccess (
@@ -641,15 +622,13 @@ const updateGitRef = (repoFullName: string, branch: string, commitSha: string, g
641622const isRefUpdateConflict = ( result : CommandResult ) : boolean =>
642623 / 4 0 9 | C o n f l i c t | R e f e r e n c e u p d a t e f a i l e d | f a s t [ - ] f o r w a r d / iu. test ( `${ result . stderr } \n${ result . stdout } ` )
643624
644- const buildUploadTreeChanges = (
625+ export const buildUploadTreeChanges = (
645626 repoFullName : string ,
646- snapshotRef : string ,
647627 existingEntries : ReadonlyArray < TreeEntry > ,
648628 desiredEntries : ReadonlyArray < UploadEntry > ,
649629 ghEnv : GhEnv
650630) : ReadonlyArray < GitTreeChange > => {
651631 const existingFileMap = buildFileMapFromTreeEntries ( existingEntries )
652- const desiredPaths = new Set ( desiredEntries . map ( ( entry ) => entry . repoPath ) )
653632 const changes : Array < GitTreeChange > = [ ]
654633 for ( const entry of desiredEntries ) {
655634 if ( existingFileMap . get ( entry . repoPath ) ?. sha === entry . blobSha ) {
@@ -662,17 +641,27 @@ const buildUploadTreeChanges = (
662641 sha : createGitBlob ( repoFullName , entry , ghEnv )
663642 } )
664643 }
665- changes . push ( ...buildSnapshotDeleteTreeEntries ( existingEntries , snapshotRef , desiredPaths ) )
666644 return changes
667645}
668646
647+ export const hasChangedUploadEntries = (
648+ existingEntries : ReadonlyArray < TreeEntry > ,
649+ desiredEntries : ReadonlyArray < UploadEntry >
650+ ) : boolean => {
651+ const existingFileMap = buildFileMapFromTreeEntries ( existingEntries )
652+ return desiredEntries . some ( ( entry ) => existingFileMap . get ( entry . repoPath ) ?. sha !== entry . blobSha )
653+ }
654+
655+ const isContentUploadEntry = ( entry : UploadEntry ) : boolean =>
656+ entry . type !== "readme" && entry . type !== "manifest"
657+
669658export const uploadSnapshot = (
670659 backupRepo : BackupRepo ,
671660 snapshotRef : string ,
672661 snapshotManifest : SnapshotManifest ,
673662 uploadEntries : ReadonlyArray < UploadEntry > ,
674663 ghEnv : GhEnv
675- ) : { readonly commitSha : string ; readonly manifestPath : string ; readonly manifestUrl : string } => {
664+ ) : { readonly changed : boolean ; readonly commitSha : string ; readonly manifestPath : string ; readonly manifestUrl : string } => {
676665 const uploadRoot = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "session-backup-api-" ) )
677666 const manifestPath = `${ snapshotRef } /manifest.json`
678667 const manifestTempPath = path . join ( uploadRoot , "manifest.json" )
@@ -691,15 +680,23 @@ export const uploadSnapshot = (
691680 if ( currentTree . headSha === undefined ) {
692681 throw new Error ( `failed to resolve ${ backupRepo . fullName } @${ backupRepo . defaultBranch } head` )
693682 }
683+ if ( ! hasChangedUploadEntries ( currentTree . entries , uploadEntries . filter ( isContentUploadEntry ) ) ) {
684+ return {
685+ changed : false ,
686+ commitSha : currentTree . headSha ,
687+ manifestPath,
688+ manifestUrl : buildBlobUrl ( backupRepo . fullName , backupRepo . defaultBranch , manifestPath )
689+ }
690+ }
694691 const changes = buildUploadTreeChanges (
695692 backupRepo . fullName ,
696- snapshotRef ,
697693 currentTree . entries ,
698694 desiredEntries ,
699695 ghEnv
700696 )
701697 if ( changes . length === 0 ) {
702698 return {
699+ changed : false ,
703700 commitSha : currentTree . headSha ,
704701 manifestPath,
705702 manifestUrl : buildBlobUrl ( backupRepo . fullName , backupRepo . defaultBranch , manifestPath )
@@ -710,6 +707,7 @@ export const uploadSnapshot = (
710707 const updateResult = updateGitRef ( backupRepo . fullName , backupRepo . defaultBranch , commitSha , ghEnv )
711708 if ( updateResult . success ) {
712709 return {
710+ changed : true ,
713711 commitSha,
714712 manifestPath,
715713 manifestUrl : buildBlobUrl ( backupRepo . fullName , backupRepo . defaultBranch , manifestPath )
0 commit comments