Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-34564] For branch projects, pick workspace names which…
… are bounded in length and avoid unusual characters.
  • Loading branch information
jglick committed Sep 17, 2016
1 parent 78766a8 commit 0405786
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 1 deletion.
63 changes: 63 additions & 0 deletions src/main/java/jenkins/branch/WorkspaceLocatorImpl.java
@@ -0,0 +1,63 @@
/*
* The MIT License
*
* Copyright 2016 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package jenkins.branch;

import com.google.common.hash.Hashing;
import hudson.Extension;
import hudson.FilePath;
import hudson.model.Node;
import hudson.model.Slave;
import hudson.model.TopLevelItem;
import hudson.remoting.Base64;
import jenkins.model.Jenkins;
import jenkins.slaves.WorkspaceLocator;

/**
* Chooses manageable workspace names for branch projects.
*/
@Extension
public class WorkspaceLocatorImpl extends WorkspaceLocator {

@Override
public FilePath locate(TopLevelItem item, Node node) {
if (!(item.getParent() instanceof MultiBranchProject)) {
return null;
}
String minimized = minimize(item.getFullName());
if (node instanceof Jenkins) {
return ((Jenkins) node).getRootPath().child("workspace/" + minimized);
} else if (node instanceof Slave) {
return ((Slave) node).getWorkspaceRoot().child(minimized);
} else { // ?
return null;
}
}

static String minimize(String name) {
return name.replaceAll("(%[0-9A-F]{2}|[^a-zA-Z0-9-_.])+", "_").replaceFirst(".*?(.{0,36}$)", "$1") + "-" +
Base64.encode(Hashing.sha256().hashString(name).asBytes()).replace('/', '_').replace('+', '.').replaceFirst("=+$", "");
}

}
71 changes: 71 additions & 0 deletions src/test/java/jenkins/branch/WorkspaceLocatorImplTest.java
@@ -0,0 +1,71 @@
/*
* The MIT License
*
* Copyright 2016 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package jenkins.branch;

import hudson.model.FreeStyleProject;
import hudson.scm.NullSCM;
import hudson.slaves.DumbSlave;
import static jenkins.branch.NoTriggerBranchPropertyTest.showComputation;
import jenkins.branch.harness.MultiBranchImpl;
import jenkins.scm.impl.SingleSCMSource;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.WithoutJenkins;

public class WorkspaceLocatorImplTest {

@Rule
public JenkinsRule r = new JenkinsRule();

@WithoutJenkins
@Test
public void minimize() {
assertEquals("stuff_dev_flow-X0yiR9.BqsTqg9pFIyiV0ATm6dyruRbTOvnNTG9SxW8", WorkspaceLocatorImpl.minimize("stuff/dev%2Fflow"));
assertEquals("some_longish_name_here_master-ftMhCUghiC48kxZS4Zw6.QohYNA35xl611Xy3HUNe.M", WorkspaceLocatorImpl.minimize("some longish name here/master"));
assertEquals("o_much_to_fit_in_a_short_path_at_all-cH_mwM17JKzXFOunEJLQFV6iV4B5V.S2Wi1AC3bM6K0", WorkspaceLocatorImpl.minimize("really way too much to fit in a short path at all"));
assertEquals("a_b_c_d-oy2E86mHig3a7JI3gjl1h1_pFxZuvFiQUZFDQ1B6_jo", WorkspaceLocatorImpl.minimize("a/b/c/d"));
}

@Issue("JENKINS-34564")
@Test
public void locate() throws Exception {
MultiBranchImpl stuff = r.createProject(MultiBranchImpl.class, "stuff");
stuff.getSourcesList().add(new BranchSource(new SingleSCMSource(null, "dev/flow", new NullSCM())));
stuff.scheduleBuild2(0).getFuture().get();
r.waitUntilNoActivity();
showComputation(stuff);
FreeStyleProject master = r.jenkins.getItemByFullName("stuff/dev%2Fflow", FreeStyleProject.class);
assertNotNull(master);
assertEquals(r.jenkins.getRootPath().child("workspace/stuff_dev_flow-X0yiR9.BqsTqg9pFIyiV0ATm6dyruRbTOvnNTG9SxW8"), r.jenkins.getWorkspaceFor(master));
DumbSlave slave = r.createOnlineSlave();
assertEquals(slave.getWorkspaceRoot().child("stuff_dev_flow-X0yiR9.BqsTqg9pFIyiV0ATm6dyruRbTOvnNTG9SxW8"), slave.getWorkspaceFor(master));
FreeStyleProject unrelated = r.createFreeStyleProject("100% crazy");
assertEquals(r.jenkins.getRootPath().child("workspace/100% crazy"), r.jenkins.getWorkspaceFor(unrelated));
}

}
Expand Up @@ -42,7 +42,7 @@ public BranchProjectFactoryImpl() {}

@Override
public FreeStyleProject newInstance(Branch branch) {
FreeStyleProject job = new FreeStyleProject(getOwner(), branch.getName());
FreeStyleProject job = new FreeStyleProject(getOwner(), branch.getEncodedName());
setBranch(job, branch);
return job;
}
Expand Down

0 comments on commit 0405786

Please sign in to comment.