@@ -224,14 +224,157 @@ public LibraryCachingConfiguration getCachingConfiguration() {
224224 * and have those SCMs tell us what we want here. But that's a job
225225 * for another day.
226226 */
227- private String defaultedVersionSCM (@ NonNull Run <?, ?> run , @ NonNull TaskListener listener , PrintStream logger ) {
227+ private boolean isDefaultedVersionSCMSupported (SCM scm ) {
228+ // Return "true" if we can extractDefaultedVersionSCM() from this SCM
229+ return ("hudson.plugins.git.GitSCM" .equals (scm .getClass ().getName ()));
230+ }
231+
232+
233+ private String extractDefaultedVersionGitSCM (@ NonNull SCM scm , @ NonNull Run <?, ?> run , @ NonNull TaskListener listener , PrintStream logger ) {
234+ if (!("hudson.plugins.git.GitSCM" .equals (scm .getClass ().getName ())))
235+ return null ;
236+
228237 String runVersion = null ;
229- Item runParent = run .getParent ();
230238
239+ // Avoid importing GitSCM and so requiring that
240+ // it is always installed even if not used by
241+ // particular Jenkins deployment (using e.g.
242+ // SVN, Gerritt, etc.). Our aim is to query this:
243+ // runVersion = scm0.getBranches().first().getExpandedName(run.getEnvironment(listener));
244+ // https://mkyong.com/java/how-to-use-reflection-to-call-java-method-at-runtime/
245+ Class noparams [] = {};
246+ Class [] paramEnvVars = new Class [1 ];
247+ paramEnvVars [0 ] = EnvVars .class ;
248+
249+ // https://javadoc.jenkins.io/plugin/git/hudson/plugins/git/GitSCM.html#getBranches() =>
250+ // https://javadoc.jenkins.io/plugin/git/hudson/plugins/git/BranchSpec.html#toString()
251+ Method methodGetBranches = null ;
252+ try {
253+ methodGetBranches = scm .getClass ().getDeclaredMethod ("getBranches" , noparams );
254+ } catch (Exception x ) {
255+ // NoSuchMethodException | SecurityException | NullPointerException
256+ methodGetBranches = null ;
257+ }
258+ if (methodGetBranches != null ) {
259+ Object branchList = null ;
260+ try {
261+ branchList = methodGetBranches .invoke (scm );
262+ } catch (Exception x ) {
263+ // InvocationTargetException | IllegalAccessException
264+ branchList = null ;
265+ }
266+ if (branchList != null && branchList instanceof List ) {
267+ Object branch0 = ((List <Object >) branchList ).get (0 );
268+ if (branch0 != null && "hudson.plugins.git.BranchSpec" .equals (branch0 .getClass ().getName ())) {
269+ Method methodGetExpandedName = null ;
270+ try {
271+ methodGetExpandedName = branch0 .getClass ().getDeclaredMethod ("getExpandedName" , paramEnvVars );
272+ } catch (Exception x ) {
273+ methodGetExpandedName = null ;
274+ }
275+ if (methodGetExpandedName != null ) {
276+ // Handle possible shell-templated branch specs:
277+ Object expandedBranchName = null ;
278+ try {
279+ expandedBranchName = methodGetExpandedName .invoke (branch0 , run .getEnvironment (listener ));
280+ } catch (Exception x ) {
281+ // IllegalAccessException | IOException
282+ expandedBranchName = null ;
283+ }
284+ if (expandedBranchName != null ) {
285+ runVersion = expandedBranchName .toString ();
286+ }
287+ } else {
288+ if (logger != null ) {
289+ logger .println ("defaultedVersion(): " +
290+ "did not find method BranchSpec.getExpandedName()" );
291+ }
292+ }
293+ if (runVersion == null || "" .equals (runVersion )) {
294+ runVersion = branch0 .toString ();
295+ }
296+ } else {
297+ // unknown branchspec class, make no blind guesses
298+ if (logger != null ) {
299+ logger .println ("defaultedVersion(): " +
300+ "list of branches did not return a " +
301+ "BranchSpec class instance, but " +
302+ (branch0 == null ? "null" :
303+ branch0 .getClass ().getName ()));
304+ }
305+ }
306+ } else {
307+ if (logger != null ) {
308+ logger .println ("defaultedVersion(): " +
309+ "getBranches() did not return a " +
310+ "list of branches: " +
311+ (branchList == null ? "null" :
312+ branchList .getClass ().getName ()));
313+ }
314+ }
315+ } else {
316+ // not really the GitSCM we know?
317+ if (logger != null ) {
318+ logger .println ("defaultedVersion(): " +
319+ "did not find method GitSCM.getBranches()" );
320+ }
321+ }
322+
323+ // Still alive? Chop off leading '*/'
324+ // (if any) from single-branch MBP and
325+ // plain "Pipeline" job definitions.
326+ if (runVersion != null ) {
327+ runVersion = runVersion .replaceFirst ("^\\ */" , "" );
328+ if (logger != null ) {
329+ logger .println ("defaultedVersion(): " +
330+ "Discovered runVersion '" + runVersion +
331+ "' in SCM source of the pipeline" );
332+ }
333+ }
334+
335+ return runVersion ;
336+ }
337+
338+ private String extractDefaultedVersionSCM (@ NonNull SCM scm , @ NonNull Run <?, ?> run , @ NonNull TaskListener listener , PrintStream logger ) {
339+ String runVersion = null ;
340+
341+ if (logger != null ) {
342+ logger .println ("defaultedVersion(): " +
343+ "inspecting first listed SCM: " +
344+ scm .toString ());
345+ }
346+
347+ // TODO: If this hack gets traction, try available methods
348+ // until a non-null result.
349+ // Ideally SCM API itself would have all classes return this
350+ // value (or null if branch concept is not supported there):
351+ runVersion = extractDefaultedVersionGitSCM (scm , run , listener , logger );
352+
353+ if (runVersion == null ) {
354+ // got SVN, Gerritt or some other SCM -
355+ // add handling when needed and known how
356+ // or rely on BRANCH_NAME (if set) below...
357+ if (logger != null ) {
358+ logger .println ("defaultedVersion(): " +
359+ "the first listed SCM was not of currently " +
360+ "supported class with recognized branch support: " +
361+ scm .getClass ().getName ());
362+ }
363+ }
364+
365+ return runVersion ;
366+ }
367+
368+ private String defaultedVersionSCM (@ NonNull Run <?, ?> run , @ NonNull TaskListener listener , PrintStream logger ) {
231369 // Ask for SCM source of the pipeline (if any),
232370 // as the most authoritative source of the branch
233- // name we want:
371+ // name we want. If we get an SCM class we can
372+ // query deeper (supports branch concept), then
373+ // extract the branch name of the script source.
234374 SCM scm0 = null ;
375+ String runVersion = null ;
376+ Item runParent = run .getParent ();
377+
235378 if (runParent != null && runParent instanceof WorkflowJob ) {
236379 // This covers both "Multibranch Pipeline"
237380 // and "Pipeline script from SCM" jobs;
@@ -263,11 +406,11 @@ private String defaultedVersionSCM(@NonNull Run<?, ?> run, @NonNull TaskListener
263406 csfd .getClass ().getName () +
264407 "' is not associated with an SCM" );
265408 }
266- } else if (!( "hudson.plugins.git.GitSCM" . equals ( scm0 . getClass (). getName ()) )) {
409+ } else if (!isDefaultedVersionSCMSupported ( scm0 )) {
267410 if (logger != null ) {
268411 logger .println ("defaultedVersion(): CpsScmFlowDefinition '" +
269412 csfd .getClass ().getName () +
270- "' is associated with an SCM we can not query: " +
413+ "' is associated with an SCM class we can not query for branches : " +
271414 scm0 .toString ());
272415 }
273416 scm0 = null ;
@@ -294,7 +437,7 @@ private String defaultedVersionSCM(@NonNull Run<?, ?> run, @NonNull TaskListener
294437 scmN .getClass ().getName () +
295438 "': " + scmN .toString ());
296439 }
297- if ("hudson.plugins.git.GitSCM" . equals (scmN . getClass (). getName () )) {
440+ if (isDefaultedVersionSCMSupported (scmN )) {
298441 // The best we can do here is accept
299442 // the first seen SCM (with branch
300443 // support which we know how to query).
@@ -364,119 +507,8 @@ private String defaultedVersionSCM(@NonNull Run<?, ?> run, @NonNull TaskListener
364507
365508 // Got some hit? Drill deeper!
366509 if (scm0 != null ) {
367- // Avoid importing GitSCM and so requiring that
368- // it is always installed even if not used by
369- // particular Jenkins deployment (using e.g.
370- // SVN, Gerritt, etc.). Our aim is to query this:
371- // runVersion = scm0.getBranches().first().getExpandedName(run.getEnvironment(listener));
372- // https://mkyong.com/java/how-to-use-reflection-to-call-java-method-at-runtime/
373- if (logger != null ) {
374- logger .println ("defaultedVersion(): " +
375- "inspecting first listed SCM: " +
376- scm0 .toString ());
377- }
378-
379- Class noparams [] = {};
380- Class [] paramEnvVars = new Class [1 ];
381- paramEnvVars [0 ] = EnvVars .class ;
382- if ("hudson.plugins.git.GitSCM" .equals (scm0 .getClass ().getName ())) {
383- // https://javadoc.jenkins.io/plugin/git/hudson/plugins/git/GitSCM.html#getBranches() =>
384- // https://javadoc.jenkins.io/plugin/git/hudson/plugins/git/BranchSpec.html#toString()
385- Method methodGetBranches = null ;
386- try {
387- methodGetBranches = scm0 .getClass ().getDeclaredMethod ("getBranches" , noparams );
388- } catch (Exception x ) {
389- // NoSuchMethodException | SecurityException | NullPointerException
390- methodGetBranches = null ;
391- }
392- if (methodGetBranches != null ) {
393- Object branchList = null ;
394- try {
395- branchList = methodGetBranches .invoke (scm0 );
396- } catch (Exception x ) {
397- // InvocationTargetException | IllegalAccessException
398- branchList = null ;
399- }
400- if (branchList != null && branchList instanceof List ) {
401- Object branch0 = ((List <Object >) branchList ).get (0 );
402- if (branch0 != null && "hudson.plugins.git.BranchSpec" .equals (branch0 .getClass ().getName ())) {
403- Method methodGetExpandedName = null ;
404- try {
405- methodGetExpandedName = branch0 .getClass ().getDeclaredMethod ("getExpandedName" , paramEnvVars );
406- } catch (Exception x ) {
407- methodGetExpandedName = null ;
408- }
409- if (methodGetExpandedName != null ) {
410- // Handle possible shell-templated branch specs:
411- Object expandedBranchName = null ;
412- try {
413- expandedBranchName = methodGetExpandedName .invoke (branch0 , run .getEnvironment (listener ));
414- } catch (Exception x ) {
415- // IllegalAccessException | IOException
416- expandedBranchName = null ;
417- }
418- if (expandedBranchName != null ) {
419- runVersion = expandedBranchName .toString ();
420- }
421- } else {
422- if (logger != null ) {
423- logger .println ("defaultedVersion(): " +
424- "did not find method BranchSpec.getExpandedName()" );
425- }
426- }
427- if (runVersion == null || "" .equals (runVersion )) {
428- runVersion = branch0 .toString ();
429- }
430- } else {
431- // unknown branchspec class, make no blind guesses
432- if (logger != null ) {
433- logger .println ("defaultedVersion(): " +
434- "list of branches did not return a " +
435- "BranchSpec class instance, but " +
436- (branch0 == null ? "null" :
437- branch0 .getClass ().getName ()));
438- }
439- }
440- } else {
441- if (logger != null ) {
442- logger .println ("defaultedVersion(): " +
443- "getBranches() did not return a " +
444- "list of branches: " +
445- (branchList == null ? "null" :
446- branchList .getClass ().getName ()));
447- }
448- }
449- } else {
450- // not really the GitSCM we know?
451- if (logger != null ) {
452- logger .println ("defaultedVersion(): " +
453- "did not find method GitSCM.getBranches()" );
454- }
455- }
456-
457- // Still alive? Chop off leading '*/'
458- // (if any) from single-branch MBP and
459- // plain "Pipeline" job definitions.
460- if (runVersion != null ) {
461- runVersion = runVersion .replaceFirst ("^\\ */" , "" );
462- if (logger != null ) {
463- logger .println ("defaultedVersion(): " +
464- "Discovered runVersion '" + runVersion +
465- "' in SCM source of the pipeline" );
466- }
467- }
468- } else {
469- // else SVN, Gerritt or some other SCM -
470- // add handling when needed and known how
471- // or rely on BRANCH_NAME (if set) below...
472- if (logger != null ) {
473- logger .println ("defaultedVersion(): " +
474- "the first listed SCM was not of currently " +
475- "supported class with recognized branch support: " +
476- scm0 .getClass ().getName ());
477- }
478- }
479- } // if (scm0 != null)
510+ runVersion = extractDefaultedVersionSCM (scm0 , run , listener , logger );
511+ }
480512
481513 return runVersion ;
482514 }
0 commit comments