From e377ce598826c66f2421589af3120cbc730c79f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 7 Nov 2018 11:52:49 +0100 Subject: [PATCH] Implement first steps for actual merge --- .../scm/repository/spi/GitMergeCommand.java | 50 ++++++++++++++---- .../repository/spi/GitMergeCommandTest.java | 43 ++++++++++++++- .../scm/repository/spi/scm-git-spi-test.zip | Bin 20891 -> 23641 bytes 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java index 6e69a2c5ba..a4b416420d 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitMergeCommand.java @@ -1,8 +1,11 @@ package sonia.scm.repository.spi; +import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.merge.MergeStrategy; import org.eclipse.jgit.merge.ResolveMerger; import org.eclipse.jgit.lib.Repository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import sonia.scm.repository.GitWorkdirFactory; import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.api.MergeCommandResult; @@ -12,23 +15,20 @@ import java.io.IOException; public class GitMergeCommand extends AbstractGitCommand implements MergeCommand { - private final GitWorkdirFactory workdirPool; + private static final Logger logger = LoggerFactory.getLogger(GitMergeCommand.class); - GitMergeCommand(GitContext context, sonia.scm.repository.Repository repository, GitWorkdirFactory workdirPool) { + private final GitWorkdirFactory workdirFactory; + + GitMergeCommand(GitContext context, sonia.scm.repository.Repository repository, GitWorkdirFactory workdirFactory) { super(context, repository); - this.workdirPool = workdirPool; + this.workdirFactory = workdirFactory; } @Override public MergeCommandResult merge(MergeCommandRequest request) { - try (WorkingCopy workingCopy = workdirPool.createWorkingCopy(context)) { + try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context)) { Repository repository = workingCopy.get(); - ResolveMerger merger = (ResolveMerger) MergeStrategy.RECURSIVE.newMerger(repository); - boolean mergeResult = merger.merge(repository.resolve(request.getBranchToMerge()), repository.resolve(request.getTargetBranch())); - if (mergeResult) { - // TODO push and verify push was successful - } - return new MergeCommandResult(mergeResult); + return new MergeWorker(repository).merge(request); } catch (IOException e) { throw new InternalRepositoryException(e); } @@ -44,4 +44,34 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand throw new InternalRepositoryException(e); } } + + private static class MergeWorker { + + private final Repository clone; + private MergeWorker(Repository clone) { + this.clone = clone; + } + + private MergeCommandResult merge(MergeCommandRequest request) throws IOException { + ResolveMerger merger = (ResolveMerger) MergeStrategy.RECURSIVE.newMerger(clone); + boolean mergeResult = merger.merge( + resolveRevision(clone, request.getTargetBranch()), + resolveRevision(clone, request.getBranchToMerge()) + ); + if (mergeResult) { + logger.info("Merged branch {} into {}", request.getBranchToMerge(), request.getTargetBranch()); + // TODO commit, push and verify push was successful + } + return new MergeCommandResult(mergeResult); + } + + private ObjectId resolveRevision(Repository repository, String branchToMerge) throws IOException { + ObjectId resolved = repository.resolve(branchToMerge); + if (resolved == null) { + return repository.resolve("origin/" + branchToMerge); + } else { + return resolved; + } + } + } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java index 3c58916807..bd140c68cb 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitMergeCommandTest.java @@ -3,7 +3,22 @@ package sonia.scm.repository.spi; import org.junit.Assert; import org.junit.Test; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + public class GitMergeCommandTest extends AbstractGitCommandTestBase { + + @Test + public void shouldDetectMergeableBranches() { + GitMergeCommand command = createCommand(); + MergeCommandRequest request = new MergeCommandRequest(); + request.setBranchToMerge("mergeable"); + request.setTargetBranch("master"); + + boolean mergeable = command.dryRun(request).isMergeable(); + + assertThat(mergeable).isTrue(); + } + @Test public void shouldDetectNotMergeableBranches() { GitMergeCommand command = createCommand(); @@ -13,10 +28,34 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase { boolean mergeable = command.dryRun(request).isMergeable(); - Assert.assertFalse(mergeable); + assertThat(mergeable).isFalse(); + } + + @Test + public void shouldMergeMergeableBranches() { + GitMergeCommand command = createCommand(); + MergeCommandRequest request = new MergeCommandRequest(); + request.setTargetBranch("master"); + request.setBranchToMerge("mergeable"); + + boolean mergeable = command.merge(request).isSuccess(); + + assertThat(mergeable).isTrue(); + } + + @Test + public void shouldNotMergeConflictingBranches() { + GitMergeCommand command = createCommand(); + MergeCommandRequest request = new MergeCommandRequest(); + request.setBranchToMerge("test-branch"); + request.setTargetBranch("master"); + + boolean mergeable = command.merge(request).isSuccess(); + + assertThat(mergeable).isFalse(); } private GitMergeCommand createCommand() { - return new GitMergeCommand(createContext(), repository, null); + return new GitMergeCommand(createContext(), repository, new SimpleGitWorkdirFactory()); } } diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-test.zip b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-test.zip index 3fbab0be38e115c7c9fe342e52ea2a4bdc4e6893..8f689e9664fc97179530c73aca4c969b1cfe962a 100644 GIT binary patch delta 7381 zcma)A2Uru?7M@H11w$1fbOb^jNFk(9rFTI@kWd6dC@MukAG)#u6_r&idslg)qH952 zJNAZcK}AH7wJj>jDvPXwE4r3Nd@~6!ff@W>_y)qAd(S!doc}-foV#fU<>4txTx2L! zNe#k2m77;HHpnVGN0LbJDXiWGl;C??#+IJ7VR!cdN7s;=nqJ zzf>2sVJx&8wW_8`xu^#H&jf}bHPot%tb$oi;uLYFL?*YA+@j;_u9s8UG^MZO>z11T zu>4wHpyiNm{?w+F2hWE8a}W`o+$0 z)|&suCGYl4y;IZ>|K>DLXYT9qQ!egXdzX_JQXP4$l+ksh;Iqp|`qH@L>R)R8X5Ex@ zjV)_4xz>7VqfP%d7k4u}7{UZNBYa)1!G!V)?eW+%%-!p@m;fcd9(Y9=KfZ$)3$R|r zN1HHyv{OZ$0;E(H$*YUhF)(;PhU^t@>=P=<3I^@v7|^eWki2r!U#tYwblpi_#p>>c zfjP`2c_o1jDd4IyoA?T-s%(%76Eed8_y{D{6bQP4KFTN#vU1WSg>q<-c?p8@|EA4N zPfkvTQ}1;K{`=is9jVFkX4m4%Rk4 zEQ;CkrI}Ax=LMEAv>zMy^fLdADy$U2rKNX1{ztd5WeVUsmoMGKM^HwKq(T5@+rMf1(;4SjpJy?Ourr_bj!o_+NRNT{m6 z*(#(@Z+Y6UraE_?a#TI7T5VZE-3LvF`^>RhAE(&XZ~K_n&)Im0(gO@u>C#T!*`52~ z>yzsCoc3SKd3NtFE3fqIPwl^T;mzv}r;V0G1JMqBW~WZJqsv$-Xr>t1$sL-W%N*h= z0YMNXBeu6E9r&2&YZJH(W}39>kG3i)Tn|h#*Pl4bdwC8LqihF-=8OpjD5?oFL5;Z= z5gte3iRu(7mc2AqEL?UN%@f`zJ`7NN%+AfoXU>(R=QA@UDQWr4Y{}dVNlNN$dD_4d z89@aEtzYet1GBXPW(n%vX=m2|^T1Ts-&@O$(XP^O;GlcfD9%WE^{>KH)1&gB!pE`h zMVf!Ji|c-qn*SXA*A|xspVjB;XV>_p-cPX1HPJSncP{bS?RUFfUcdQ$-ftgz{!REY zGby%ciL_KuBUq+y^{an(7Ba)=!MyOJF_}e%PkY5@XL$A@Kl%TnRv%-3Mk{RXe~}3* z*$XPTQ&M^V?DbnSySq$cxUA(|Ny;y~=a-zTy4Cwu6N`y1U`^5o6D_QX?g7&+>U8C~ z6ywmM)32^Nqj{7y4&<5YO0m>J;)J^Oi8*&!TBTc0?|Wl8_W0Wi9(#QJ;j%!#Sk{TF z*?!+g{unh~=dWb3;QaZ#c<(v({?D%mZ*JuOY23Q`eqxvdsA+tp78Y!v$+pcBA9K}G zTG6m%rS7`K$ctGyhcooE=z(b&EiVh)T%~5!LUHTUtnK&1Y?VdyF+ZMv{$p>(oX#`p z>9;o3+HF0_Oga)(rsKP;D7EB8^{%Ygn<)qd zJ@`(l`LX!)(<22pLiWFmGyUDqa^=~XYY(irR7w4NLS4j_c`4n?nBmgvZv_SW9lRWN z_FhbvR(1eZs@b8gBh%*V`5*aphx)atNj$eJ2E@E9m#&Kl@^uMcy|=*poX$>R1^u`M zSFNUF+xk1rl!=iEE3?Z#i47N?Ny%=h@S|CdbDV!{U%;NKkLy00wLM%Oc3-F;dMlvo zWnb^(*VolcJ@&@U&-~+c%_F~wCRy9ty7bs>7ryH~VR~qx^1;j0x}G=v6IyrmtBkqk zD#|w9b>QF`zl{m?p_gw*6-{lmQlh!%T%x?or1bavCWzZuX|soB0a?M_6;8+V@00{G zwu|NmmoJ5HoY)mJF+S(}iDqWc+NKM(TxdGmwS80C#f7Imsa_QP{KDu6Y%ERm$XSME z9I%RK_>F8q2YC!N@Ru!3+j-;(2gcfow0|F2Nq~I28c<Fja#o(M6%c9rPzBHK;wL>6SzAO@}E# z4h^@a1=)u*hBiHgp$##rA7m$FQn(zwrd+Z}yK%{oRn3hB40~G=%q7{2NL+i}UI;uK z$>fV1$&gg%7z+Yyj7=nbxkrIFA=Fl#Ir!yH-_BzKY$rvpQ30p1zV>b4T8WL>9 zp|B&;YiKyIXIMzs%v7N;O(J9o(#2^kE}zfg3k508Y_T&-kiz4pNK)7-E-oBrSx6LB zNr#Muph8Oa>ckK#Teq~R$-eu$IoH01Z3`NgSbSz>Qw5^Fu5ZOjsPpX$lz%=>cXs@qNK9WQv@xPyI^-rG+$ zeN^#H30p5ijcK49HH#3MHUaBkBO>AuNQ=2(kmcClvD2($a*foYWNbD~}`Qu=p%iI)@N3)uD)i z7Hel-wb}*us@T3yS$Enzx2onpe4w1&ux2A2D)Hg?etxI^Z(D2hqwvkAnyq&wol0)L zI-?Qdm)V>IM)uYqnL{JtM-hjNADtYbiF5k5ur9SBJ4L!|UZAIft+v`oXah3`viUza z+yiQSE%Y>_fi|9oJ|Tq;Wb1=L^5_bjX!_en${v{W6`iw*qXvqcI3$d}=w!kdq7mBu zydvBVjSlvxqG>K7DmZXPkiWN|%<~vVhz<2kz6)xl#dt!^4nbg!fK8J4j|$vKM!yOW zn&O242PSr zkCkMg6~7!Im}Mic6F|3zDJXW;fX~5Tt*ic+0qa168v^&i;G-KdG^B|RO;!RPZni^1 z4(k#TXjAFc`%Lh#72(&5`xMq!AQ)BCxk9 z$nZ27GPc&w6wo|1%(!Ndyx*J_jV^ujXk_rQd7mORr1^vMWH2Y6JUon8PmFD0@S_C{ zZc7V#?R|2XJb9lhlZtiF!|*4Q3T}JZP$}jRXf`*HqK2|G?+r)kpl&%Nu>)avSFH%i zsEGr6CZ{Yap1>4E@xXbKx#~2F0U6*>BqMXwxZ-Uqmh*5Uc9vvW4hR?>--AkVK7-0h zh8ArMXsAS#xr|_~j2N*I8a5Nrl5((`{1!lJ{SY|Q8ocr|9s-D_KLQ`H1|I%CLqk>G z2wZCe8olvZJ>CeFY72oLE3Pi;x0jDc;>XDsrIam5@Wt0i(V+%gaKIOr+#iB4HlxXO z&{lQ|dH|yG=xrnA*`Nxa*+JmEB^UhQjgv1Y7=fGY!RBCG&joa7yaRY0jO)=0L>Lf) z>){LJdO``fUmk)`{SgRcu(+TrWVoJ72nd^u>&cyrz$%Vl%Vb*FtewFT5lR7hJ$P1rph%~5ukbBAE9pIK%mH;3tR*65I+fY zq&Ndw5bl0v5H^w+gvV%g7y|2X!MQMeQX4uH%LVG;qr^zoh{$84>4MuQ#M%`JLbHdSMu=GjIu9=$h(%^=Bm&>_0IE}rhPL1^1%VAcLEIF}ZvxAZvD$M$ zwn7;}pcAl-M5ryE5cnCr&YBgeo1)?nAGIt`1A>JvGM82qlS%6?}xYwoBCAhJ!`Hd z;_%uy2=VN(barm8F4ujUZjO6F{xqF?p1#n1VnOy)ods=RCpI9M*EC+$cUt&esKc!p}s|I_l% z$~MgXQk*w4%zys0T-{tFca50;cqS1=t^Eu0va+&>i5Xv}6x)=jxhtP=mskBgVB^^{ zH-27JQqn3*8_rv5)^@_i->Ld@x@Gwv1OGkw_1^pmZ(}o+2PIF-($^{@+uVlj>^ty@ z;6lZQb8F#{%-%3DD>-_7QQLvODyx8|I18KO!H=3Iyxq~FuI5=-?r41_UH^}^y%nV; zVVMzTlkL(@tGRYo{+Hs1{{(J^0@V%%(#*jsbs&uLq`Wjm)YHQ{76_{m>Ih1(V8tCvH3+u=C7WUg;0{4KDJQF&~fH72g-tG~HQu>P6Yk zp*C^h3k@{^!7pM|E#sYbJevMfQ_Z=Cnj@_ret+q)a`Se?k(;S*2V9;V^1S8pT4jCh zwyL4Uw^Az37ZfhPf8yz$q0f$-auDVeb55!1LZx*XB{h*RMy+vpKT}Ysm=SGoi0Ef{ z_ISy>ml5}0J3PHVY5m2z#WP=Mo%J$$qMbWQe}pOn=)^|s2@o*Nr~ zx1=%%t#Jcjm7C+hUNUUDEK~GXBcaw!?2!BLPAWqZzPLrObYZGH?)Hjdb}(a*g!vf$ zHmDYA$pP>|%y*=2SOzRYz*k6IeX|wDjukv+GyT|0%cqL1$Ndb&GG|EgN`y*pFSz6> zWhr%zRLd6=U+Wb}Js`n{O@5(|mQURoJ?*^ok;9?{JMd9kz+P#8N0u0jB-bSf;E6Pp zzv%7P7xUXdKbY_B3+udWz&lvlD?+M9042ep{EG}9t_L^5yEt2zuCjtsi6u*{dnH=_ zSVpV^JP$*DkPwPh{aJK2sI)9O^-tq$pRQ8 z4`s=jUfuvQiMJiImGIDVfv`|#_D605jcZfaV#L%(@Czw|ec`qa)P=!#4mZO?_>7ed z3c~#1QiLDNlm3x%_-B}cCEJ4VAuRH_;iMyn5OG=dPe_ZDj%8Uh(-LU~<~}LF(-$E; zbkX*bZ2W0jF3k{^S<%ZPNofrh>D(T%5Vbw_D0^z8Q|8vR3Vgdmr(g@Yx}u!I{OL3E z_0vYDvnj)wD3Z9vftOK^eLA*eh>j%*I|8Q1l3hnrqe)^07dAypyN)Wb)G;%-8SB+` z)E`TgnL|i4t#}0=HT8k_-4s1zNTS{nM#s=t4`WC!vPV$rI0$@Vt-1gg#gG;)0}%RF zub)z+fJd>ykzK32DQMFs!`vB7L}2DH$5k$Nu=!C!vQA`g!B_9>vCpxaLedE z2u~!5u^v#6DD0}EQhc<<15PGJcO4ywCy7;q;Xynt^(CI<-WrU+U8<&>ZT>nW7@tBC z>0(%!LhDrGqYYwsm_j3;(vV`Ygm%*}$W#Ss47`g8BzLj|L6cMs-idVB)}u&qsAo5X zJQG6JqpwJYVH%Ps@q}3#+I(}I2(HCj%WI`HfSMYJ|1bA&NFuQ5>=_OkTw>vc;EF^I z8{=uW=8qr=7jM`%f)2k9A7y#NA0ue{IDF!PH$2zSQZ{2qVxSDd#?VsNlSm?iglp-v z)T?xo*hGTsXj%$m$sOf%907s7P}$i5kmVdIf8k9YWO&kcK_ZOQf%kb4UAe) zF)6PZta@jXT#XNcYoTgbl}RI*Cz0Y`yCE3&42;06K}{0L6(|rWWokH{L?cjPn%)|n`gtyPZ;p)de`87}H-Yb@a3Q{Y$tZEJdV z&J>e1#uNoS1qc)fBJF@KFv``4K!m#eW5-xA%xg?NmgFu9M9>m$4|B%S!8YRa_xQXa u!l}o_Hbjf(X%OUVUAl~|z(>_Va7^pr)@{a_nNt^W4E`C1+tVwU`s;r;+;4^e