Skip to content
Permalink
Browse files
Merge branch 'master' into JENKINS-14325
Conflicts:
	changelog.html
  • Loading branch information
jglick committed Jul 10, 2012
2 parents d66b2e5 + 051b001 commit ae3dac8afb6eef325958285b5a13bc933f5aacb6
@@ -58,12 +58,21 @@
<li class=bug>
Enable/disable GUI for jobs either did not appear, or threw exceptions, for jobs inside folders
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-14325">issue 14325</a>)
<li class=bug>
<code>NullPointerException</code> from <code>UnlabeldLoadStatistics</code> <i>[sic]</i>
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-14330">issue 14330</a>)
<li class=bug>
Incorrect display of list items in project changes for SCMs such as Mercurial.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-14365">issue 14365</a>)
</ul>
</div><!--=TRUNK-END=-->

<!-- these changes are controlled by the release process. DO NOT MODIFY -->
<div id="rc" style="display:none;"><!--=BEGIN=-->
<h3><a name=v1.474>What's new in 1.474</a> <!--=DATE=--></h3>
<h3><a name=v1.475>What's new in 1.475</a> <!--=DATE=--></h3>
<!--=RC-CHANGES=-->
</div><!--=END=-->
<h3><a name=v1.474>What's new in 1.474</a> (2012/07/09)</h3>
<ul class=image>
<li class=bug>
Fix French translation
@@ -75,7 +84,6 @@ <h3><a name=v1.474>What's new in 1.474</a> <!--=DATE=--></h3>
Added a new extension point to listen to polling activities.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-14178">issue 14178</a>)
</ul>
</div><!--=END=-->
<h3><a name=v1.473>What's new in 1.473</a> (2012/07/01)</h3>
<ul class=image>
<li class=bug>
@@ -937,7 +937,7 @@ public Set<String> getSensitiveBuildVariables() {
* <p>
* This mechanism is used by {@link MatrixConfiguration} to pass
* the configuration values to the current build. It is up to
* {@link Builder}s to decide whether it wants to recognize the values
* {@link Builder}s to decide whether they want to recognize the values
* or how to use them.
*
* <p>
@@ -88,6 +88,7 @@
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.Inet4Address;
import javax.annotation.CheckForNull;

import static javax.servlet.http.HttpServletResponse.*;

@@ -425,7 +426,7 @@ public String getName() {
* null if the configuration has changed and the node is removed, yet the corresponding {@link Computer}
* is not yet gone.
*/
public Node getNode() {
public @CheckForNull Node getNode() {
if(nodeName==null)
return Jenkins.getInstance();
return Jenkins.getInstance().getNode(nodeName);
@@ -33,13 +33,11 @@
import hudson.util.DescriptorList;
import hudson.util.XStream2;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
import java.util.*;

/**
* Convenience methods related to {@link Item}.
@@ -63,7 +61,7 @@ public static DescriptorExtensionList<TopLevelItem,TopLevelItemDescriptor> all()
}

public static TopLevelItemDescriptor getDescriptor(String fqcn) {
return Descriptor.find(all(),fqcn);
return Descriptor.find(all(), fqcn);
}

/**
@@ -104,6 +102,102 @@ public static <T extends Item> List<T> fromNameList(ItemGroup context, String li
return r;
}

/**
* Computes the canonical full name of a relative path in an {@link ItemGroup} context, handling relative
* positions ".." and "." as absolute path starting with "/". The resulting name is the item fullName from Jenkins
* root.
*/
public static String getCanonicalName(ItemGroup context, String path) {
String[] c = context.getFullName().split("/");
String[] p = path.split("/");

Stack name = new Stack();
for (int i=0; i<c.length;i++) {
if (i==0 && c[i].equals("")) continue;
name.push(c[i]);
}
for (int i=0; i<p.length;i++) {
if (i==0 && p[i].equals("")) {
// Absolute path starting with a "/"
name.clear();
continue;
}
if (p[i].equals("..")) {
name.pop();
continue;
}
if (p[i].equals(".")) {
continue;
}
name.push(p[i]);
}
return StringUtils.join(name, '/');
}

/**
* Compute the relative name of list of items after a rename occurred. Used to manage job references as names in
* plugins to support {@link hudson.model.listeners.ItemListener#onRenamed(hudson.model.Item, String, String)}.
* <p>
* In a hierarchical context, when a plugin has a reference to a job as <code>../foo/bar</code> this method will
* handle the relative path as "foo" is renamed to "zot" to compute <code>../zot/bar</code>
*
* @param oldFullName the old full name of the item
* @param newFullName the new full name of the item
* @param relativeNames coma separated list of Item relative names
* @param context the {link ItemGroup} relative names refer to
* @return relative name for the renamed item, based on the same ItemGroup context
*/
public static String computeRelativeNamesAfterRenaming(String oldFullName, String newFullName, String relativeNames, ItemGroup context) {

StringTokenizer tokens = new StringTokenizer(relativeNames,",");
List<String> newValue = new ArrayList<String>();
while(tokens.hasMoreTokens()) {
String relativeName = tokens.nextToken().trim();
String canonicalName = getCanonicalName(context, relativeName);
if (canonicalName.startsWith(oldFullName)) {
String newCanonicalName = newFullName + canonicalName.substring(oldFullName.length());
// relative name points to the renamed item, let's compute the new relative name
newValue.add( computeRelativeNameAfterRenaming(canonicalName, newCanonicalName, relativeName) );
} else {
newValue.add(relativeName);
}
}
return StringUtils.join(newValue, ",");
}

/**
* Compute the relative name of an Item after renaming
*/
private static String computeRelativeNameAfterRenaming(String oldFullName, String newFullName, String relativeName) {

String[] a = oldFullName.split("/");
String[] n = newFullName.split("/");
assert a.length == n.length;
String[] r = relativeName.split("/");

int j = a.length-1;
for(int i=r.length-1;i>=0;i--) {
String part = r[i];
if (part.equals("") && i==0) {
continue;
}
if (part.equals(".")) {
continue;
}
if (part.equals("..")) {
j--;
continue;
}
if (part.equals(a[j])) {
r[i] = n[j];
j--;
continue;
}
}
return StringUtils.join(r, '/');
}


/**
* Loads a {@link Item} from a config file.
*
@@ -26,7 +26,6 @@
import hudson.model.MultiStageTimeSeries.TimeScale;
import hudson.model.MultiStageTimeSeries.TrendChart;
import jenkins.model.Jenkins;
import jenkins.model.UnlabeldLoadStatistics;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.export.Exported;
@@ -590,7 +590,7 @@ protected void onModified() throws IOException {
* @since 1.467
*/
@Exported
public transient final LoadStatistics unlabeledLoad = new UnlabeldLoadStatistics();
public transient final LoadStatistics unlabeledLoad = new UnlabeledLoadStatistics();

/**
* {@link NodeProvisioner} that reacts to {@link #unlabeledLoad}.
@@ -39,27 +39,32 @@
* @see OverallLoadStatistics
* @author Kohsuke Kawaguchi
*/
public class UnlabeldLoadStatistics extends LoadStatistics {
public class UnlabeledLoadStatistics extends LoadStatistics {

UnlabeldLoadStatistics() {
UnlabeledLoadStatistics() {
super(0, 0);
}

@Override
public int computeIdleExecutors() {
int r=0;
for (Computer c : Jenkins.getInstance().getComputers())
if(c.getNode().getMode()== Mode.NORMAL && (c.isOnline() || c.isConnecting()))
for (Computer c : Jenkins.getInstance().getComputers()) {
Node node = c.getNode();
if (node != null && node.getMode() == Mode.NORMAL && (c.isOnline() || c.isConnecting())) {
r += c.countIdle();
}
}
return r;
}

@Override
public int computeTotalExecutors() {
int r=0;
for (Computer c : Jenkins.getInstance().getComputers()) {
if(c.getNode().getMode()==Mode.NORMAL && c.isOnline())
Node node = c.getNode();
if (node != null && node.getMode() == Mode.NORMAL && c.isOnline()) {
r += c.countExecutors();
}
}
return r;
}
@@ -48,7 +48,7 @@ THE SOFTWARE.

<ol>
<j:forEach var="c" items="${b.changeSet.iterator()}" varStatus="loop">
<li value="${c.revision}">
<li value="${c.revision.class.name == 'java.lang.Integer' ? c.revision : null}">
<j:out value="${c.msgAnnotated}"/>

&#8212;
@@ -0,0 +1,62 @@
package hudson.model;

import org.junit.BeforeClass;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.Collection;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

/**
* @author: <a hef="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
*/
public class ItemsTest {

private static ItemGroup root;
private static ItemGroup foo;
private static ItemGroup foo_bar;

@BeforeClass
public static void itemGroups() {
root = mock(ItemGroup.class);
when(root.getFullName()).thenReturn("");

foo = mock(ItemGroup.class);
when(foo.getFullName()).thenReturn("foo");

foo_bar = mock(ItemGroup.class);
when(foo_bar.getFullName()).thenReturn("foo/bar");

}

@Test
public void getCanonicalName() {
assertEquals("foo", Items.getCanonicalName(root, "foo"));
assertEquals("foo", Items.getCanonicalName(root, "/foo"));
assertEquals("foo/bar", Items.getCanonicalName(root, "foo/bar"));
assertEquals("foo/bar", Items.getCanonicalName(foo, "bar"));
assertEquals("bar", Items.getCanonicalName(foo, "/bar"));
assertEquals("bar", Items.getCanonicalName(foo, "../bar"));
assertEquals("foo/bar", Items.getCanonicalName(foo, "./bar"));
assertEquals("foo/bar/baz/qux", Items.getCanonicalName(foo_bar, "baz/qux"));
assertEquals("foo/baz/qux", Items.getCanonicalName(foo_bar, "../baz/qux"));
}

@Test
public void computeRelativeNamesAfterRenaming() {
assertEquals("meu,bu,zo", Items.computeRelativeNamesAfterRenaming("ga", "meu", "ga,bu,zo", root ));
assertEquals("ga,bu,zo", Items.computeRelativeNamesAfterRenaming("ga", "meu", "ga,bu,zo", foo_bar ));
assertEquals("meu,bu,zo", Items.computeRelativeNamesAfterRenaming("foo/ga", "foo/meu", "ga,bu,zo", foo ));

assertEquals("/meu,/bu,/zo", Items.computeRelativeNamesAfterRenaming("ga", "meu", "/ga,/bu,/zo", root ));
assertEquals("/meu,/bu,/zo", Items.computeRelativeNamesAfterRenaming("ga", "meu", "/ga,/bu,/zo", foo_bar ));

assertEquals("../meu,../bu,../zo", Items.computeRelativeNamesAfterRenaming("ga", "meu", "../ga,../bu,../zo", foo ));
assertEquals("../qux/ga,bu,zo", Items.computeRelativeNamesAfterRenaming("foo/baz", "foo/qux", "../baz/ga,bu,zo", foo_bar ));
}

}
@@ -1,3 +1,9 @@
jenkins (1.474) unstable; urgency=low

* See http://jenkins-ci.org/changelog for more details.

-- Kohsuke Kawaguchi <kk@kohsuke.org> Mon, 09 Jul 2012 17:37:53 -0700

jenkins (1.473) unstable; urgency=low

* See http://jenkins-ci.org/changelog for more details.
@@ -217,6 +217,7 @@
*
* @see <a href="http://wiki.jenkins-ci.org/display/JENKINS/Unit+Test+JUnit4">Wiki article about unit testing in Jenkins</a>
* @author Stephen Connolly
* @since 1.436
*/
public class JenkinsRule implements TestRule, RootAction {

0 comments on commit ae3dac8

Please sign in to comment.