@@ -85,7 +85,9 @@ const makeFileChanges = async (
8585 | "with-executable-file"
8686 | "with-ignored-symlink"
8787 | "with-included-valid-symlink"
88- | "with-included-invalid-symlink" ,
88+ | "with-included-invalid-symlink"
89+ | "with-unchanged-symlink"
90+ | "with-changed-symlink" ,
8991) => {
9092 // Update an existing file
9193 await fs . promises . writeFile (
@@ -164,6 +166,40 @@ const makeFileChanges = async (
164166 path . join ( repoDirectory , "some-dir" , "nested" ) ,
165167 ) ;
166168 }
169+ if (
170+ changegroup === "with-unchanged-symlink" ||
171+ changegroup === "with-changed-symlink"
172+ ) {
173+ // Create a symlink and commit it locally first
174+ await fs . promises . mkdir ( path . join ( repoDirectory , "some-dir" ) , {
175+ recursive : true ,
176+ } ) ;
177+ await fs . promises . symlink (
178+ path . join ( repoDirectory , "README.md" ) ,
179+ path . join ( repoDirectory , "some-dir" , "nested" ) ,
180+ ) ;
181+ // Commit the symlink locally so it's in the base commit tree
182+ await git . add ( {
183+ fs,
184+ dir : repoDirectory ,
185+ filepath : "some-dir/nested" ,
186+ } ) ;
187+ await git . commit ( {
188+ fs,
189+ dir : repoDirectory ,
190+ message : "Add symlink" ,
191+ author : { name : "Test" , email : "test@test.com" } ,
192+ } ) ;
193+
194+ if ( changegroup === "with-changed-symlink" ) {
195+ // Change the symlink to point to a different target
196+ await fs . promises . rm ( path . join ( repoDirectory , "some-dir" , "nested" ) ) ;
197+ await fs . promises . symlink (
198+ path . join ( repoDirectory , "LICENSE" ) ,
199+ path . join ( repoDirectory , "some-dir" , "nested" ) ,
200+ ) ;
201+ }
202+ }
167203} ;
168204
169205const makeFileChangeAssertions = async ( branch : string ) => {
@@ -264,7 +300,11 @@ describe("git", () => {
264300 describe ( "commitChangesFromRepo" , ( ) => {
265301 const testDir = path . join ( ROOT_TEMP_DIRECTORY , "commitChangesFromRepo" ) ;
266302
267- for ( const group of [ "standard" , "with-ignored-symlink" ] as const ) {
303+ for ( const group of [
304+ "standard" ,
305+ "with-ignored-symlink" ,
306+ "with-unchanged-symlink" ,
307+ ] as const ) {
268308 it ( `should correctly commit all changes for group: ${ group } ` , async ( ) => {
269309 const branch = `${ TEST_BRANCH_PREFIX } -multiple-changes-${ group } ` ;
270310 branches . push ( branch ) ;
@@ -414,6 +454,51 @@ describe("git", () => {
414454 "Unexpected symlink at some-dir/nested, GitHub API only supports files and directories. You may need to add this file to .gitignore" ,
415455 ) ;
416456 } ) ;
457+
458+ it ( `and symlink was changed` , async ( ) => {
459+ const branch = `${ TEST_BRANCH_PREFIX } -changed-symlink-error` ;
460+ branches . push ( branch ) ;
461+
462+ await fs . promises . mkdir ( testDir , { recursive : true } ) ;
463+ const repoDirectory = path . join ( testDir , `repo-changed-symlink` ) ;
464+
465+ // Clone the git repo locally using the git cli and child-process
466+ await new Promise < void > ( ( resolve , reject ) => {
467+ const p = execFile (
468+ "git" ,
469+ [ "clone" , process . cwd ( ) , `repo-changed-symlink` ] ,
470+ { cwd : testDir } ,
471+ ( error ) => {
472+ if ( error ) {
473+ reject ( error ) ;
474+ } else {
475+ resolve ( ) ;
476+ }
477+ } ,
478+ ) ;
479+ p . stdout ?. pipe ( process . stdout ) ;
480+ p . stderr ?. pipe ( process . stderr ) ;
481+ } ) ;
482+
483+ await makeFileChanges ( repoDirectory , "with-changed-symlink" ) ;
484+
485+ // Push the changes
486+ await expect ( ( ) =>
487+ commitChangesFromRepo ( {
488+ octokit,
489+ ...REPO ,
490+ branch,
491+ message : {
492+ headline : "Test commit" ,
493+ body : "This is a test commit" ,
494+ } ,
495+ cwd : repoDirectory ,
496+ log,
497+ } ) ,
498+ ) . rejects . toThrow (
499+ "Unexpected symlink at some-dir/nested, GitHub API only supports files and directories. You may need to add this file to .gitignore" ,
500+ ) ;
501+ } ) ;
417502 } ) ;
418503
419504 it ( `should throw appropriate error when executable file is present` , async ( ) => {
0 commit comments