diff --git a/core/src/main/java/hudson/model/Run.java b/core/src/main/java/hudson/model/Run.java index d45927c5868957b3536f5edeb9016634e6991ba8..8f789b3e4b2bb6a5712d3550e22adf0154023cb2 100644 --- a/core/src/main/java/hudson/model/Run.java +++ b/core/src/main/java/hudson/model/Run.java @@ -50,6 +50,9 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.Locale; +import java.util.Set; +import java.util.HashSet; +import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -487,8 +490,9 @@ public abstract class Run ,RunT extends Run getArtifacts() { - List r = new ArrayList(); + ArtifactList r = new ArtifactList(); addArtifacts(getArtifactsDir(),"",r); + r.computeDisplayName(); return r; } @@ -519,6 +523,77 @@ public abstract class Run ,RunT extends Run { + public void computeDisplayName() { + if(size()>CUTOFF) return; // we are not going to display file names, so no point in computing this + + int maxDepth = 0; + int[] len = new int[size()]; + String[][] tokens = new String[size()][]; + for( int i=0; i names = new HashMap(); + for (int i = 0; i < tokens.length; i++) { + String[] token = tokens[i]; + String displayName = combineLast(token,len[i]); + Integer j = names.put(displayName, i); + if(j!=null) { + collision = true; + if(j>=0) + len[j]++; + len[i]++; + names.put(displayName,-1); // occupy this name but don't let len[i] incremented with additional collisions + } + } + } while(collision && depth++ names = new HashSet(); +// for (String[] token : tokens) { +// if(!names.add(combineLast(token,n))) +// continue OUTER; // collision. Increase n and try again +// } +// +// // this n successfully diambiguates +// for (int i = 0; i < tokens.length; i++) { +// String[] token = tokens[i]; +// get(i).displayPath = combineLast(token,n); +// } +// return; +// } + +// // it's impossible to get here, as that means +// // we have the same artifacts archived twice, but be defensive +// for (Artifact a : this) +// a.displayPath = a.relativePath; + } + + /** + * Combines last N token into the "a/b/c" form. + */ + private String combineLast(String[] token, int n) { + StringBuffer buf = new StringBuffer(); + for( int i=Math.max(0,token.length-n); i0) buf.append('/'); + buf.append(token[i]); + } + return buf.toString(); + } + } + /** * A build artifact. */ @@ -526,9 +601,15 @@ public abstract class Run ,RunT extends Run,RunT extends Run
  • - ${f.fileName} + ${f.displayPath} [fingerprint]
  • diff --git a/core/src/test/java/hudson/model/RunTest.java b/core/src/test/java/hudson/model/RunTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4be3de736574d53b8e1445f84f361bead1857c29 --- /dev/null +++ b/core/src/test/java/hudson/model/RunTest.java @@ -0,0 +1,42 @@ +package hudson.model; + +import junit.framework.TestCase; + +import java.util.GregorianCalendar; +import java.util.List; + +/** + * @author Kohsuke Kawaguchi + */ +public class RunTest extends TestCase { + private List.Artifact> createArtifactList(String... paths) { + Run r = new Run(null,new GregorianCalendar()) { + }; + Run.ArtifactList list = r.new ArtifactList(); + for (String p : paths) { + list.add(r.new Artifact(p)); + } + list.computeDisplayName(); + return list; + } + + public void testArtifactListDisambiguation1() { + List.Artifact> a = createArtifactList("a/b/c.xml", "d/f/g.xml", "h/i/j.xml"); + assertEquals(a.get(0).getDisplayPath(),"c.xml"); + assertEquals(a.get(1).getDisplayPath(),"g.xml"); + assertEquals(a.get(2).getDisplayPath(),"j.xml"); + } + + public void testArtifactListDisambiguation2() { + List.Artifact> a = createArtifactList("a/b/c.xml", "d/f/g.xml", "h/i/g.xml"); + assertEquals(a.get(0).getDisplayPath(),"c.xml"); + assertEquals(a.get(1).getDisplayPath(),"f/g.xml"); + assertEquals(a.get(2).getDisplayPath(),"i/g.xml"); + } + + public void testArtifactListDisambiguation3() { + List.Artifact> a = createArtifactList("a.xml","a/a.xml"); + assertEquals(a.get(0).getDisplayPath(),"a.xml"); + assertEquals(a.get(1).getDisplayPath(),"a/a.xml"); + } +}