@@ -80,6 +80,7 @@ func testGitGeneral(t *testing.T, u *url.URL) {
8080		mediaTest (t , & httpContext , pushedFilesStandard [0 ], pushedFilesStandard [1 ], pushedFilesLFS [0 ], pushedFilesLFS [1 ])
8181
8282		t .Run ("CreateAgitFlowPull" , doCreateAgitFlowPull (dstPath , & httpContext , "test/head" ))
83+ 		t .Run ("CreateProtectedBranch" , doCreateProtectedBranch (& httpContext , dstPath ))
8384		t .Run ("BranchProtectMerge" , doBranchProtectPRMerge (& httpContext , dstPath ))
8485		t .Run ("AutoMerge" , doAutoPRMerge (& httpContext , dstPath ))
8586		t .Run ("CreatePRAndSetManuallyMerged" , doCreatePRAndSetManuallyMerged (httpContext , httpContext , dstPath , "master" , "test-manually-merge" ))
@@ -121,6 +122,7 @@ func testGitGeneral(t *testing.T, u *url.URL) {
121122			mediaTest (t , & sshContext , pushedFilesStandard [0 ], pushedFilesStandard [1 ], pushedFilesLFS [0 ], pushedFilesLFS [1 ])
122123
123124			t .Run ("CreateAgitFlowPull" , doCreateAgitFlowPull (dstPath , & sshContext , "test/head2" ))
125+ 			t .Run ("CreateProtectedBranch" , doCreateProtectedBranch (& sshContext , dstPath ))
124126			t .Run ("BranchProtectMerge" , doBranchProtectPRMerge (& sshContext , dstPath ))
125127			t .Run ("MergeFork" , func (t  * testing.T ) {
126128				defer  tests .PrintCurrentTest (t )()
@@ -325,6 +327,34 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
325327	return  filepath .Base (tmpFile .Name ()), err 
326328}
327329
330+ func  doCreateProtectedBranch (baseCtx  * APITestContext , dstPath  string ) func (t  * testing.T ) {
331+ 	return  func (t  * testing.T ) {
332+ 		defer  tests .PrintCurrentTest (t )()
333+ 		ctx  :=  NewAPITestContext (t , baseCtx .Username , baseCtx .Reponame , auth_model .AccessTokenScopeWriteRepository )
334+ 
335+ 		t .Run ("ProtectBranchWithFilePatterns" , doProtectBranch (ctx , "release-*" , baseCtx .Username , "" , "" , "config*" ))
336+ 
337+ 		// push a new branch without any new commits 
338+ 		t .Run ("CreateProtectedBranch-NoChanges" , doGitCreateBranch (dstPath , "release-v1.0" ))
339+ 		t .Run ("PushProtectedBranch-NoChanges" , doGitPushTestRepository (dstPath , "origin" , "release-v1.0" ))
340+ 		t .Run ("CheckoutMaster-NoChanges" , doGitCheckoutBranch (dstPath , "master" ))
341+ 
342+ 		// push a new branch with a new unprotected file 
343+ 		t .Run ("CreateProtectedBranch-UnprotectedFile" , doGitCreateBranch (dstPath , "release-v2.0" ))
344+ 		_ , 
err  :=  generateCommitWithNewData (
testFileSizeSmall , 
dstPath , 
"[email protected] " , 
"User Two" , 
"abc.txt" )
 345+ 		assert .NoError (t , err )
346+ 		t .Run ("PushProtectedBranch-UnprotectedFile" , doGitPushTestRepository (dstPath , "origin" , "release-v2.0" ))
347+ 		t .Run ("CheckoutMaster-UnprotectedFile" , doGitCheckoutBranch (dstPath , "master" ))
348+ 
349+ 		// push a new branch with a new protected file 
350+ 		t .Run ("CreateProtectedBranch-ProtectedFile" , doGitCreateBranch (dstPath , "release-v3.0" ))
351+ 		_ , 
err  =  generateCommitWithNewData (
testFileSizeSmall , 
dstPath , 
"[email protected] " , 
"User Two" , 
"config" )
 352+ 		assert .NoError (t , err )
353+ 		t .Run ("PushProtectedBranch-ProtectedFile" , doGitPushTestRepositoryFail (dstPath , "origin" , "release-v3.0" ))
354+ 		t .Run ("CheckoutMaster-ProtectedFile" , doGitCheckoutBranch (dstPath , "master" ))
355+ 	}
356+ }
357+ 
328358func  doBranchProtectPRMerge (baseCtx  * APITestContext , dstPath  string ) func (t  * testing.T ) {
329359	return  func (t  * testing.T ) {
330360		defer  tests .PrintCurrentTest (t )()
@@ -334,27 +364,23 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
334364		ctx  :=  NewAPITestContext (t , baseCtx .Username , baseCtx .Reponame , auth_model .AccessTokenScopeWriteRepository )
335365
336366		// Protect branch without any whitelisting 
337- 		t .Run ("ProtectBranchNoWhitelist" , func (t  * testing.T ) {
338- 			doProtectBranch (ctx , "protected" , "" , "" , "" )
339- 		})
367+ 		t .Run ("ProtectBranchNoWhitelist" , doProtectBranch (ctx , "protected" , "" , "" , "" , "" ))
340368
341369		// Try to push without permissions, which should fail 
342370		t .Run ("TryPushWithoutPermissions" , func (t  * testing.T ) {
343371			_ , 
err  :=  generateCommitWithNewData (
testFileSizeSmall , 
dstPath , 
"[email protected] " , 
"User Two" , 
"branch-data-file-" )
 344372			assert .NoError (t , err )
345- 			doGitPushTestRepositoryFail (dstPath , "origin" , "protected" )
373+ 			doGitPushTestRepositoryFail (dstPath , "origin" , "protected" )( t ) 
346374		})
347375
348376		// Set up permissions for normal push but not force push 
349- 		t .Run ("SetupNormalPushPermissions" , func (t  * testing.T ) {
350- 			doProtectBranch (ctx , "protected" , baseCtx .Username , "" , "" )
351- 		})
377+ 		t .Run ("SetupNormalPushPermissions" , doProtectBranch (ctx , "protected" , baseCtx .Username , "" , "" , "" ))
352378
353379		// Normal push should work 
354380		t .Run ("NormalPushWithPermissions" , func (t  * testing.T ) {
355381			_ , 
err  :=  generateCommitWithNewData (
testFileSizeSmall , 
dstPath , 
"[email protected] " , 
"User Two" , 
"branch-data-file-" )
 356382			assert .NoError (t , err )
357- 			doGitPushTestRepository (dstPath , "origin" , "protected" )
383+ 			doGitPushTestRepository (dstPath , "origin" , "protected" )( t ) 
358384		})
359385
360386		// Try to force push without force push permissions, which should fail 
@@ -364,30 +390,22 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
364390				_ , 
err  :=  generateCommitWithNewData (
testFileSizeSmall , 
dstPath , 
"[email protected] " , 
"User Two" , 
"branch-data-file-new" )
 365391				assert .NoError (t , err )
366392			})
367- 			doGitPushTestRepositoryFail (dstPath , "-f" , "origin" , "protected" )
393+ 			doGitPushTestRepositoryFail (dstPath , "-f" , "origin" , "protected" )( t ) 
368394		})
369395
370396		// Set up permissions for force push but not normal push 
371- 		t .Run ("SetupForcePushPermissions" , func (t  * testing.T ) {
372- 			doProtectBranch (ctx , "protected" , "" , baseCtx .Username , "" )
373- 		})
397+ 		t .Run ("SetupForcePushPermissions" , doProtectBranch (ctx , "protected" , "" , baseCtx .Username , "" , "" ))
374398
375399		// Try to force push without normal push permissions, which should fail 
376- 		t .Run ("ForcePushWithoutNormalPermissions" , func (t  * testing.T ) {
377- 			doGitPushTestRepositoryFail (dstPath , "-f" , "origin" , "protected" )
378- 		})
400+ 		t .Run ("ForcePushWithoutNormalPermissions" , doGitPushTestRepositoryFail (dstPath , "-f" , "origin" , "protected" ))
379401
380402		// Set up permissions for normal and force push (both are required to force push) 
381- 		t .Run ("SetupNormalAndForcePushPermissions" , func (t  * testing.T ) {
382- 			doProtectBranch (ctx , "protected" , baseCtx .Username , baseCtx .Username , "" )
383- 		})
403+ 		t .Run ("SetupNormalAndForcePushPermissions" , doProtectBranch (ctx , "protected" , baseCtx .Username , baseCtx .Username , "" , "" ))
384404
385405		// Force push should now work 
386- 		t .Run ("ForcePushWithPermissions" , func (t  * testing.T ) {
387- 			doGitPushTestRepository (dstPath , "-f" , "origin" , "protected" )
388- 		})
406+ 		t .Run ("ForcePushWithPermissions" , doGitPushTestRepository (dstPath , "-f" , "origin" , "protected" ))
389407
390- 		t .Run ("ProtectProtectedBranchNoWhitelist" , doProtectBranch (ctx , "protected" , "" , "" , "" ))
408+ 		t .Run ("ProtectProtectedBranchNoWhitelist" , doProtectBranch (ctx , "protected" , "" , "" , "" ,  "" ))
391409		t .Run ("PushToUnprotectedBranch" , doGitPushTestRepository (dstPath , "origin" , "protected:unprotected" ))
392410		var  pr  api.PullRequest 
393411		var  err  error 
@@ -409,14 +427,14 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
409427		t .Run ("MergePR" , doAPIMergePullRequest (ctx , baseCtx .Username , baseCtx .Reponame , pr .Index ))
410428		t .Run ("PullProtected" , doGitPull (dstPath , "origin" , "protected" ))
411429
412- 		t .Run ("ProtectProtectedBranchUnprotectedFilePaths" , doProtectBranch (ctx , "protected" , "" , "" , "unprotected-file-*" ))
430+ 		t .Run ("ProtectProtectedBranchUnprotectedFilePaths" , doProtectBranch (ctx , "protected" , "" , "" , "unprotected-file-*" ,  "" ))
413431		t .Run ("GenerateCommit" , func (t  * testing.T ) {
414432			_ , 
err  :=  generateCommitWithNewData (
testFileSizeSmall , 
dstPath , 
"[email protected] " , 
"User Two" , 
"unprotected-file-" )
 415433			assert .NoError (t , err )
416434		})
417435		t .Run ("PushUnprotectedFilesToProtectedBranch" , doGitPushTestRepository (dstPath , "origin" , "protected" ))
418436
419- 		t .Run ("ProtectProtectedBranchWhitelist" , doProtectBranch (ctx , "protected" , baseCtx .Username , "" , "" ))
437+ 		t .Run ("ProtectProtectedBranchWhitelist" , doProtectBranch (ctx , "protected" , baseCtx .Username , "" , "" ,  "" ))
420438
421439		t .Run ("CheckoutMaster" , doGitCheckoutBranch (dstPath , "master" ))
422440		t .Run ("CreateBranchForced" , doGitCreateBranch (dstPath , "toforce" ))
@@ -431,7 +449,7 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes
431449	}
432450}
433451
434- func  doProtectBranch (ctx  APITestContext , branch , userToWhitelistPush , userToWhitelistForcePush , unprotectedFilePatterns  string ) func (t  * testing.T ) {
452+ func  doProtectBranch (ctx  APITestContext , branch , userToWhitelistPush , userToWhitelistForcePush , unprotectedFilePatterns ,  protectedFilePatterns  string ) func (t  * testing.T ) {
435453	// We are going to just use the owner to set the protection. 
436454	return  func (t  * testing.T ) {
437455		csrf  :=  GetUserCSRFToken (t , ctx .Session )
@@ -440,6 +458,7 @@ func doProtectBranch(ctx APITestContext, branch, userToWhitelistPush, userToWhit
440458			"_csrf" :                     csrf ,
441459			"rule_name" :                 branch ,
442460			"unprotected_file_patterns" : unprotectedFilePatterns ,
461+ 			"protected_file_patterns" :   protectedFilePatterns ,
443462		}
444463
445464		if  userToWhitelistPush  !=  ""  {
0 commit comments