3838import hudson .plugins .git .extensions .impl .PreBuildMerge ;
3939import hudson .scm .NullSCM ;
4040import hudson .tasks .BuildStepDescriptor ;
41+ import hudson .tasks .Builder ;
4142import hudson .util .StreamTaskListener ;
4243import org .eclipse .jgit .lib .Constants ;
4344import org .eclipse .jgit .lib .ObjectId ;
4445import org .jenkinsci .plugins .gitclient .MergeCommand ;
4546import org .jvnet .hudson .test .Issue ;
4647
48+ import java .io .File ;
4749import java .io .IOException ;
4850import java .util .ArrayList ;
4951import java .util .Collections ;
5052import java .util .List ;
51- import java .util .Map ;
5253import java .util .Set ;
53- import java .util .regex .Matcher ;
54- import java .util .regex .Pattern ;
5554import java .util .concurrent .atomic .AtomicInteger ;
5655import jenkins .plugins .git .CliGitCommand ;
5756import org .eclipse .jgit .lib .PersonIdent ;
@@ -141,7 +140,7 @@ public void testMergeAndPush() throws Exception {
141140
142141 project .getPublishersList ().add (new GitPublisher (
143142 Collections .<TagToPush >emptyList (),
144- Collections .singletonList (new BranchToPush ("origin" , "integration" )),
143+ Collections .singletonList (new BranchToPush ("origin" , "integration" , false )),
145144 Collections .<NoteToPush >emptyList (),
146145 true , true , false ));
147146
@@ -178,7 +177,7 @@ public void testMergeAndPushFF() throws Exception {
178177
179178 project .getPublishersList ().add (new GitPublisher (
180179 Collections .<TagToPush >emptyList (),
181- Collections .singletonList (new BranchToPush ("origin" , "integration" )),
180+ Collections .singletonList (new BranchToPush ("origin" , "integration" , false )),
182181 Collections .<NoteToPush >emptyList (),
183182 true , true , false ));
184183
@@ -263,7 +262,7 @@ public void testMergeAndPushNoFF() throws Exception {
263262
264263 project .getPublishersList ().add (new GitPublisher (
265264 Collections .<TagToPush >emptyList (),
266- Collections .singletonList (new BranchToPush ("origin" , "integration" )),
265+ Collections .singletonList (new BranchToPush ("origin" , "integration" , false )),
267266 Collections .<NoteToPush >emptyList (),
268267 true , true , false ));
269268
@@ -352,7 +351,7 @@ public void testMergeAndPushFFOnly() throws Exception {
352351
353352 project .getPublishersList ().add (new GitPublisher (
354353 Collections .<TagToPush >emptyList (),
355- Collections .singletonList (new BranchToPush ("origin" , "integration" )),
354+ Collections .singletonList (new BranchToPush ("origin" , "integration" , false )),
356355 Collections .<NoteToPush >emptyList (),
357356 true , true , false ));
358357
@@ -455,7 +454,7 @@ public void testPushEnvVarsInRemoteConfig() throws Exception{
455454
456455 project .getPublishersList ().add (new GitPublisher (
457456 Collections .singletonList (new TagToPush ("$TARGET_NAME" , tag_name , "" , false , false )),
458- Collections .singletonList (new BranchToPush ("$TARGET_NAME" , "$TARGET_BRANCH" )),
457+ Collections .singletonList (new BranchToPush ("$TARGET_NAME" , "$TARGET_BRANCH" , false )),
459458 Collections .singletonList (new NoteToPush ("$TARGET_NAME" , note_content , Constants .R_NOTES_COMMITS , false )),
460459 true , false , true ));
461460
@@ -486,7 +485,7 @@ public void testForcePush() throws Exception {
486485
487486 GitPublisher forcedPublisher = new GitPublisher (
488487 Collections .<TagToPush >emptyList (),
489- Collections .singletonList (new BranchToPush ("origin" , "otherbranch" )),
488+ Collections .singletonList (new BranchToPush ("origin" , "otherbranch" , false )),
490489 Collections .<NoteToPush >emptyList (),
491490 true , true , true );
492491 project .getPublishersList ().add (forcedPublisher );
@@ -533,7 +532,7 @@ public void testForcePush() throws Exception {
533532 project .getPublishersList ().remove (forcedPublisher );
534533 GitPublisher unforcedPublisher = new GitPublisher (
535534 Collections .<TagToPush >emptyList (),
536- Collections .singletonList (new BranchToPush ("origin" , "otherbranch" )),
535+ Collections .singletonList (new BranchToPush ("origin" , "otherbranch" , false )),
537536 Collections .<NoteToPush >emptyList (),
538537 true , true , false );
539538 project .getPublishersList ().add (unforcedPublisher );
@@ -583,7 +582,7 @@ public void testMergeAndPushWithSkipTagEnabled() throws Exception {
583582
584583 project .getPublishersList ().add (new GitPublisher (
585584 Collections .<TagToPush >emptyList (),
586- Collections .singletonList (new BranchToPush ("origin" , "integration" )),
585+ Collections .singletonList (new BranchToPush ("origin" , "integration" , false )),
587586 Collections .<NoteToPush >emptyList (),
588587 true , true , false ));
589588
@@ -602,6 +601,47 @@ public void testMergeAndPushWithSkipTagEnabled() throws Exception {
602601 assertEquals (sha1 , testGitClient .revParse (Constants .HEAD ).name ());
603602 }
604603
604+ @ Test
605+ public void testRebaseBeforePush () throws Exception {
606+ FreeStyleProject project = setupSimpleProject ("master" );
607+
608+ GitSCM scm = new GitSCM (
609+ remoteConfigs (),
610+ Collections .singletonList (new BranchSpec ("master" )),
611+ false , Collections .<SubmoduleConfig >emptyList (),
612+ null , null ,
613+ Collections .<GitSCMExtension >emptyList ());
614+ project .setScm (scm );
615+
616+ GitPublisher rebasedPublisher = new GitPublisher (
617+ Collections .<TagToPush >emptyList (),
618+ Collections .singletonList (new BranchToPush ("origin" , "master" , true )),
619+ Collections .<NoteToPush >emptyList (),
620+ true , true , true );
621+ project .getPublishersList ().add (rebasedPublisher );
622+
623+ project .getBuildersList ().add (new LongRunningCommit (testGitDir ));
624+ project .save ();
625+
626+ // Assume during our build someone else pushed changes (commitFile1) to the remote repo.
627+ // So our own changes (commitFile2) cannot be pushed back to the remote origin.
628+ //
629+ // * 0eb2599 (HEAD) Added a file named commitFile2
630+ // | * 64e71e7 (origin/master) Added a file named commitFile1
631+ // |/
632+ // * b2578eb init
633+ //
634+ // What we can do is to fetch the remote changes and rebase our own changes:
635+ //
636+ // * 0e7674c (HEAD) Added a file named commitFile2
637+ // * 64e71e7 (origin/master) Added a file named commitFile1
638+ // * b2578eb init
639+
640+
641+ // as we have set "rebaseBeforePush" to true we expect all files to be present after the build.
642+ FreeStyleBuild build = build (project , Result .SUCCESS , "commitFile1" , "commitFile2" );
643+ }
644+
605645 @ Issue ("JENKINS-24786" )
606646 @ Test
607647 public void testMergeAndPushWithCharacteristicEnvVar () throws Exception {
@@ -658,7 +698,7 @@ private void checkEnvVar(FreeStyleProject project, String envName, String envVal
658698 String noteValue = "note for " + envValue ;
659699 GitPublisher publisher = new GitPublisher (
660700 Collections .singletonList (new TagToPush ("origin" , tagNameReference , tagMessageReference , false , true )),
661- Collections .singletonList (new BranchToPush ("origin" , envReference )),
701+ Collections .singletonList (new BranchToPush ("origin" , envReference , false )),
662702 Collections .singletonList (new NoteToPush ("origin" , noteReference , Constants .R_NOTES_COMMITS , false )),
663703 true , true , true );
664704 assertTrue (publisher .isForcePush ());
@@ -739,3 +779,29 @@ private boolean isWindows() {
739779 return java .io .File .pathSeparatorChar ==';' ;
740780 }
741781}
782+
783+ class LongRunningCommit extends Builder {
784+
785+ private File remoteGitDir ;
786+
787+ LongRunningCommit (File remoteGitDir ) {
788+ this .remoteGitDir = remoteGitDir ;
789+ }
790+
791+ @ Override
792+ public boolean perform (AbstractBuild <?, ?> build , Launcher launcher , BuildListener listener ) throws InterruptedException , IOException {
793+
794+ TestGitRepo workspaceGit = new TestGitRepo ("workspace" , new File (build .getWorkspace ().getRemote ()), listener );
795+ TestGitRepo remoteGit = new TestGitRepo ("remote" , this .remoteGitDir , listener );
796+
797+ // simulate an external commit and push to the remote during the build of our project.
798+ ObjectId headRev = remoteGit .git .revParse ("HEAD" );
799+ remoteGit .commit ("commitFile1" , remoteGit .johnDoe , "Added a file commitFile1" );
800+ remoteGit .git .checkout (headRev .getName ()); // allow to push to this repo later
801+
802+ // checkout initial commit and create another head with our changes.
803+ workspaceGit .commit ("commitFile2" , remoteGit .johnDoe , "Added a file commitFile2" );
804+
805+ return true ;
806+ }
807+ }
0 commit comments