3939import hudson .scm .SCM ;
4040import hudson .util .FormValidation ;
4141
42- import java .io .ByteArrayOutputStream ;
4342import java .io .File ;
4443import java .io .FileOutputStream ;
4544import java .io .IOException ;
6059
6160import javax .servlet .ServletException ;
6261
62+ import hudson .util .IOUtils ;
6363import net .sf .json .JSONObject ;
6464
6565import org .eclipse .jgit .lib .Config ;
@@ -858,9 +858,10 @@ public boolean getAuthorOrCommitter() {
858858
859859 @ Override
860860 public boolean checkout (final AbstractBuild build , Launcher launcher ,
861- final FilePath workspace , final BuildListener listener , File changelogFile )
861+ final FilePath workspace , final BuildListener listener , File _changelogFile )
862862 throws IOException , InterruptedException {
863- Object [] returnData ; // Changelog, BuildData
863+
864+ final FilePath changelogFile = new FilePath (_changelogFile );
864865
865866 listener .getLogger ().println ("Checkout:" + workspace .getName () + " / " + workspace .getRemote () + " - " + workspace .getChannel ());
866867 listener .getLogger ().println ("Using strategy: " + buildChooser .getDisplayName ());
@@ -1056,157 +1057,144 @@ public Revision invoke(File localWorkspace, VirtualChannel channel)
10561057 listener .getLogger ().println ("Commencing build of " + revToBuild );
10571058 environment .put (GIT_COMMIT , revToBuild .getSha1String ());
10581059
1059- if (mergeOptions .doMerge ()) {
1060- if (!revToBuild .containsBranchName (mergeOptions .getRemoteBranchName ())) {
1061- returnData = workingDirectory .act (new FileCallable <Object []>() {
1062-
1063- private static final long serialVersionUID = 1L ;
1060+ if (mergeOptions .doMerge () && !revToBuild .containsBranchName (mergeOptions .getRemoteBranchName ())) {
1061+ build .addAction (workingDirectory .act (new FileCallable <BuildData >() {
10641062
1065- public Object [] invoke (File localWorkspace , VirtualChannel channel )
1066- throws IOException {
1067- IGitAPI git = new GitAPI (gitExe , new FilePath (localWorkspace ), listener , environment );
1063+ private static final long serialVersionUID = 1L ;
10681064
1069- // Do we need to merge this revision onto MergeTarget
1065+ public BuildData invoke (File localWorkspace , VirtualChannel channel )
1066+ throws IOException , InterruptedException {
1067+ IGitAPI git = new GitAPI (gitExe , new FilePath (localWorkspace ), listener , environment );
10701068
1071- // Only merge if there's a branch to merge that isn't
1072- // us..
1073- listener .getLogger ().println (
1074- "Merging " + revToBuild + " onto "
1075- + mergeOptions .getMergeTarget ());
1069+ // Do we need to merge this revision onto MergeTarget
10761070
1077- // checkout origin/blah
1078- ObjectId target = git .revParse (mergeOptions .getRemoteBranchName ());
1071+ // Only merge if there's a branch to merge that isn't
1072+ // us..
1073+ listener .getLogger ().println (
1074+ "Merging " + revToBuild + " onto "
1075+ + mergeOptions .getMergeTarget ());
10791076
1080- git .checkoutBranch (paramLocalBranch , target .name ());
1077+ // checkout origin/blah
1078+ ObjectId target = git .revParse (mergeOptions .getRemoteBranchName ());
10811079
1082- try {
1083- git .merge (revToBuild .getSha1 ().name ());
1084- } catch (Exception ex ) {
1085- listener .getLogger ().println (
1086- "Branch not suitable for integration as it does not merge cleanly" );
1087-
1088- // We still need to tag something to prevent
1089- // repetitive builds from happening - tag the
1090- // candidate
1091- // branch.
1092- git .checkoutBranch (paramLocalBranch , revToBuild .getSha1 ().name ());
1093-
1094- if (!getSkipTag ()) {
1095- git .tag (buildnumber , "Jenkins Build #"
1096- + buildNumber );
1097- }
1098-
1099- buildData .saveBuild (new Build (revToBuild , buildNumber , Result .FAILURE ));
1100- return new Object []{null , buildData };
1101- }
1080+ git .checkoutBranch (paramLocalBranch , target .name ());
11021081
1103- if (git .hasGitModules ()) {
1104- // This ensures we don't miss changes to submodule paths and allows
1105- // seamless use of bare and non-bare superproject repositories.
1106- git .setupSubmoduleUrls (revToBuild , listener );
1107- git .submoduleUpdate (recursiveSubmodules );
1108- }
1082+ try {
1083+ git .merge (revToBuild .getSha1 ().name ());
1084+ } catch (Exception ex ) {
1085+ // We still need to tag something to prevent
1086+ // repetitive builds from happening - tag the
1087+ // candidate
1088+ // branch.
1089+ git .checkoutBranch (paramLocalBranch , revToBuild .getSha1 ().name ());
11091090
11101091 if (!getSkipTag ()) {
1111- // Tag the successful merge
1112- git .tag (buildnumber , "Jenkins Build #" + buildNumber );
1113- }
1114-
1115- String changeLog = computeChangeLog (git , revToBuild , listener , buildData );
1116-
1117- Build build = new Build (revToBuild , buildNumber , null );
1118- buildData .saveBuild (build );
1119- GitUtils gu = new GitUtils (listener , git );
1120- build .mergeRevision = gu .getRevisionForSHA1 (target );
1121- if (getClean ()) {
1122- listener .getLogger ().println ("Cleaning workspace" );
1123- git .clean ();
1124- if (git .hasGitModules ()) {
1125- git .submoduleClean (recursiveSubmodules );
1126- }
1092+ git .tag (buildnumber , "Jenkins Build #"
1093+ + buildNumber );
11271094 }
11281095
1129- // Fetch the diffs into the changelog file
1130- return new Object []{ changeLog , buildData } ;
1096+ buildData . saveBuild ( new Build ( revToBuild , buildNumber , Result . FAILURE ));
1097+ throw new AbortException ( "Branch not suitable for integration as it does not merge cleanly" ) ;
11311098 }
1132- });
1133- BuildData returningBuildData = (BuildData ) returnData [1 ];
1134- build .addAction (returningBuildData );
1135- return changeLogResult ((String ) returnData [0 ], changelogFile );
1136- }
1137- }
11381099
1139- // No merge
1100+ if (git .hasGitModules ()) {
1101+ // This ensures we don't miss changes to submodule paths and allows
1102+ // seamless use of bare and non-bare superproject repositories.
1103+ git .setupSubmoduleUrls (revToBuild , listener );
1104+ git .submoduleUpdate (recursiveSubmodules );
1105+ }
11401106
1141- returnData = workingDirectory .act (new FileCallable <Object []>() {
1107+ if (!getSkipTag ()) {
1108+ // Tag the successful merge
1109+ git .tag (buildnumber , "Jenkins Build #" + buildNumber );
1110+ }
11421111
1143- private static final long serialVersionUID = 1L ;
1112+ computeChangeLog ( git , revToBuild , listener , buildData , changelogFile ) ;
11441113
1145- public Object [] invoke (File localWorkspace , VirtualChannel channel )
1146- throws IOException {
1147- IGitAPI git = new GitAPI (gitExe , new FilePath (localWorkspace ), listener , environment );
1148-
1149- // Straight compile-the-branch
1150- listener .getLogger ().println ("Checking out " + revToBuild );
1114+ Build build = new Build (revToBuild , buildNumber , null );
1115+ buildData .saveBuild (build );
1116+ GitUtils gu = new GitUtils (listener , git );
1117+ build .mergeRevision = gu .getRevisionForSHA1 (target );
1118+ if (getClean ()) {
1119+ listener .getLogger ().println ("Cleaning workspace" );
1120+ git .clean ();
1121+ if (git .hasGitModules ()) {
1122+ git .submoduleClean (recursiveSubmodules );
1123+ }
1124+ }
11511125
1152- if (getClean ()) {
1153- listener .getLogger ().println ("Cleaning workspace" );
1154- git .clean ();
1126+ // Fetch the diffs into the changelog file
1127+ return buildData ;
11551128 }
1129+ }));
1130+ } else {
1131+ // No merge
1132+ build .addAction (workingDirectory .act (new FileCallable <BuildData >() {
11561133
1157- git .checkoutBranch (paramLocalBranch , revToBuild .getSha1 ().name ());
1158-
1159- if (git .hasGitModules ()) {
1160- // Git submodule update will only 'fetch' from where it
1161- // regards as 'origin'. However,
1162- // it is possible that we are building from a
1163- // RemoteRepository with changes
1164- // that are not in 'origin' AND it may be a new module that
1165- // we've only just discovered.
1166- // So - try updating from all RRs, then use the submodule
1167- // Update to do the checkout
1168- //
1169- // Also, only do this if we're not doing recursive submodules, since that'll
1170- // theoretically be dealt with there anyway.
1171- if (!recursiveSubmodules ) {
1172- for (RemoteConfig remoteRepository : paramRepos ) {
1173- fetchSubmodulesFrom (git , localWorkspace , listener , remoteRepository );
1174- }
1175- }
1134+ private static final long serialVersionUID = 1L ;
11761135
1177- // This ensures we don't miss changes to submodule paths and allows
1178- // seamless use of bare and non-bare superproject repositories.
1179- git .setupSubmoduleUrls (revToBuild , listener );
1180- git .submoduleUpdate (recursiveSubmodules );
1136+ public BuildData invoke (File localWorkspace , VirtualChannel channel )
1137+ throws IOException , InterruptedException {
1138+ IGitAPI git = new GitAPI (gitExe , new FilePath (localWorkspace ), listener , environment );
11811139
1182- }
1140+ // Straight compile-the-branch
1141+ listener .getLogger ().println ("Checking out " + revToBuild );
11831142
1184- // if(compileSubmoduleCompares)
1185- if (doGenerateSubmoduleConfigurations ) {
1186- SubmoduleCombinator combinator = new SubmoduleCombinator (
1187- git , listener , localWorkspace , submoduleCfg );
1188- combinator .createSubmoduleCombinations ();
1189- }
1143+ if (getClean ()) {
1144+ listener .getLogger ().println ("Cleaning workspace" );
1145+ git .clean ();
1146+ }
11901147
1191- if (!getSkipTag ()) {
1192- // Tag the successful merge
1193- git .tag (buildnumber , "Jenkins Build #" + buildNumber );
1194- }
1148+ git .checkoutBranch (paramLocalBranch , revToBuild .getSha1 ().name ());
1149+
1150+ if (git .hasGitModules ()) {
1151+ // Git submodule update will only 'fetch' from where it
1152+ // regards as 'origin'. However,
1153+ // it is possible that we are building from a
1154+ // RemoteRepository with changes
1155+ // that are not in 'origin' AND it may be a new module that
1156+ // we've only just discovered.
1157+ // So - try updating from all RRs, then use the submodule
1158+ // Update to do the checkout
1159+ //
1160+ // Also, only do this if we're not doing recursive submodules, since that'll
1161+ // theoretically be dealt with there anyway.
1162+ if (!recursiveSubmodules ) {
1163+ for (RemoteConfig remoteRepository : paramRepos ) {
1164+ fetchSubmodulesFrom (git , localWorkspace , listener , remoteRepository );
1165+ }
1166+ }
11951167
1196- String changeLog = computeChangeLog (git , revToBuild , listener , buildData );
1168+ // This ensures we don't miss changes to submodule paths and allows
1169+ // seamless use of bare and non-bare superproject repositories.
1170+ git .setupSubmoduleUrls (revToBuild , listener );
1171+ git .submoduleUpdate (recursiveSubmodules );
11971172
1198- buildData . saveBuild ( new Build ( revToBuild , buildNumber , null ));
1173+ }
11991174
1200- // Fetch the diffs into the changelog file
1201- return new Object []{changeLog , buildData };
1202- }
1203- });
1175+ // if(compileSubmoduleCompares)
1176+ if (doGenerateSubmoduleConfigurations ) {
1177+ SubmoduleCombinator combinator = new SubmoduleCombinator (
1178+ git , listener , localWorkspace , submoduleCfg );
1179+ combinator .createSubmoduleCombinations ();
1180+ }
12041181
1182+ if (!getSkipTag ()) {
1183+ // Tag the successful merge
1184+ git .tag (buildnumber , "Jenkins Build #" + buildNumber );
1185+ }
1186+
1187+ computeChangeLog (git , revToBuild , listener , buildData ,changelogFile );
12051188
1206- build . addAction (( Action ) returnData [ 1 ] );
1189+ buildData . saveBuild ( new Build ( revToBuild , buildNumber , null ) );
12071190
1208- return changeLogResult ((String ) returnData [0 ], changelogFile );
1191+ // Fetch the diffs into the changelog file
1192+ return buildData ;
1193+ }
1194+ }));
1195+ }
12091196
1197+ return true ;
12101198 }
12111199
12121200 /**
@@ -1222,16 +1210,16 @@ public Object[] invoke(File localWorkspace, VirtualChannel channel)
12221210 * Information that captures what we did during the last build. We need this for changelog,
12231211 * or else we won't know where to stop.
12241212 */
1225- private String computeChangeLog (IGitAPI git , Revision revToBuild , BuildListener listener , BuildData buildData ) throws IOException {
1213+ private void computeChangeLog (IGitAPI git , Revision revToBuild , BuildListener listener , BuildData buildData , FilePath changelogFile ) throws IOException , InterruptedException {
12261214 int histories = 0 ;
12271215
1228- StringBuilder changeLog = new StringBuilder ( );
1216+ PrintStream out = new PrintStream ( changelogFile . write () );
12291217 try {
12301218 for (Branch b : revToBuild .getBranches ()) {
12311219 Build lastRevWas = buildChooser .prevBuildForChangelog (b .getName (), buildData , git );
12321220 if (lastRevWas != null ) {
12331221 if (git .isCommitInRepo (lastRevWas .getSHA1 ().name ())) {
1234- changeLog . append ( putChangelogDiffsIntoFile ( git , b .name , lastRevWas .getSHA1 ().name (), revToBuild .getSha1 ().name ()) );
1222+ putChangelogDiffs ( git , b .name , lastRevWas .getSHA1 ().name (), revToBuild .getSha1 ().name (), out );
12351223 histories ++;
12361224 } else {
12371225 listener .getLogger ().println ("Could not record history. Previous build's commit, " + lastRevWas .getSHA1 ().name ()
@@ -1242,14 +1230,14 @@ private String computeChangeLog(IGitAPI git, Revision revToBuild, BuildListener
12421230 }
12431231 }
12441232 } catch (GitException ge ) {
1245- changeLog .append ("Unable to retrieve changeset" );
1233+ out .println ("Unable to retrieve changeset" );
1234+ } finally {
1235+ IOUtils .closeQuietly (out );
12461236 }
12471237
12481238 if (histories > 1 ) {
12491239 listener .getLogger ().println ("Warning : There are multiple branch changesets here" );
12501240 }
1251-
1252- return changeLog .toString ();
12531241 }
12541242
12551243 public void buildEnvVars (AbstractBuild <?, ?> build , java .util .Map <String , String > env ) {
@@ -1268,17 +1256,10 @@ public void buildEnvVars(AbstractBuild<?, ?> build, java.util.Map<String, String
12681256
12691257 }
12701258
1271- private String putChangelogDiffsIntoFile (IGitAPI git , String branchName , String revFrom ,
1272- String revTo ) throws IOException {
1273- ByteArrayOutputStream fos = new ByteArrayOutputStream ();
1274- // fos.write("<data><![CDATA[".getBytes());
1275- String changeset = "Changes in branch " + branchName + ", between " + revFrom + " and " + revTo + "\n " ;
1276- fos .write (changeset .getBytes ());
1277-
1259+ private void putChangelogDiffs (IGitAPI git , String branchName , String revFrom ,
1260+ String revTo , PrintStream fos ) throws IOException {
1261+ fos .println ("Changes in branch " + branchName + ", between " + revFrom + " and " + revTo );
12781262 git .changelog (revFrom , revTo , fos );
1279- // fos.write("]]></data>".getBytes());
1280- fos .close ();
1281- return fos .toString ("UTF-8" );
12821263 }
12831264
12841265 @ Override
0 commit comments