Small cleanup, diffs are computed in generic indexing part (but not completelly correct, esp. for svn), first test attempt.
1.1 --- a/server/hudson/src/main/java/org/netbeans/api/jackpot/hudson/IndexBuilder.java Wed Dec 22 13:43:37 2010 +0100
1.2 +++ b/server/hudson/src/main/java/org/netbeans/api/jackpot/hudson/IndexBuilder.java Mon Dec 27 15:06:57 2010 +0100
1.3 @@ -49,6 +49,7 @@
1.4 import hudson.model.Hudson;
1.5 import java.io.File;
1.6 import java.io.IOException;
1.7 +import java.util.Set;
1.8
1.9 /**
1.10 *
1.11 @@ -60,7 +61,7 @@
1.12 return (IndexBuilderDescriptor)Hudson.getInstance().getDescriptor(getClass());
1.13 }
1.14
1.15 - public abstract boolean index(File cacheDir, AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException;
1.16 + public abstract boolean index(IndexingContext context) throws InterruptedException, IOException;
1.17
1.18 public static DescriptorExtensionList<IndexBuilder, IndexBuilderDescriptor> all() {
1.19 return Hudson.getInstance().getDescriptorList(IndexBuilder.class);
1.20 @@ -74,5 +75,22 @@
1.21 }
1.22 }
1.23
1.24 + public static final class IndexingContext {
1.25 + public final File cacheDir;
1.26 + public final AbstractBuild<?, ?> build;
1.27 + public final Launcher launcher;
1.28 + public final BuildListener listener;
1.29 + public final Set<String> addedOrModified;
1.30 + public final Set<String> removed;
1.31 +
1.32 + public IndexingContext(File cacheDir, AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener, Set<String> addedOrModified, Set<String> removed) {
1.33 + this.cacheDir = cacheDir;
1.34 + this.build = build;
1.35 + this.launcher = launcher;
1.36 + this.listener = listener;
1.37 + this.addedOrModified = addedOrModified;
1.38 + this.removed = removed;
1.39 + }
1.40 +
1.41 + }
1.42 }
1.43 -
2.1 --- a/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/IndexingBuilder.java Wed Dec 22 13:43:37 2010 +0100
2.2 +++ b/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/IndexingBuilder.java Mon Dec 27 15:06:57 2010 +0100
2.3 @@ -46,6 +46,9 @@
2.4 import hudson.model.Descriptor;
2.5 import hudson.model.Descriptor.FormException;
2.6 import hudson.model.Hudson;
2.7 +import hudson.scm.ChangeLogSet.AffectedFile;
2.8 +import hudson.scm.ChangeLogSet.Entry;
2.9 +import hudson.scm.EditType;
2.10 import hudson.tasks.Builder;
2.11 import java.io.BufferedReader;
2.12 import java.io.BufferedWriter;
2.13 @@ -53,7 +56,6 @@
2.14 import java.io.FileInputStream;
2.15 import java.io.FileOutputStream;
2.16 import java.io.IOException;
2.17 -import java.io.InputStream;
2.18 import java.io.InputStreamReader;
2.19 import java.io.OutputStreamWriter;
2.20 import java.io.Reader;
2.21 @@ -69,6 +71,7 @@
2.22 import org.kohsuke.stapler.StaplerRequest;
2.23 import org.netbeans.api.jackpot.hudson.IndexBuilder;
2.24 import org.netbeans.api.jackpot.hudson.IndexBuilder.IndexBuilderDescriptor;
2.25 +import org.netbeans.api.jackpot.hudson.IndexBuilder.IndexingContext;
2.26
2.27 /**
2.28 *
2.29 @@ -120,10 +123,23 @@
2.30
2.31 @Override
2.32 public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
2.33 + Set<String> addedFiles = new HashSet<String>();
2.34 + Set<String> removedFiles = new HashSet<String>();
2.35 +
2.36 + for (Entry e : build.getChangeSet()) {
2.37 + for (AffectedFile f : e.getAffectedFiles()) {
2.38 + if (f.getEditType() == EditType.DELETE) {
2.39 + removedFiles.add(stripLeadingSlash(f.getPath()));
2.40 + } else {
2.41 + addedFiles.add(stripLeadingSlash(f.getPath()));
2.42 + }
2.43 + }
2.44 + }
2.45 +
2.46 boolean success = true;
2.47
2.48 for (IndexBuilder indexer : getIndexers()) {
2.49 - success &= indexer.index(getDescriptor().getCacheDir(), build, launcher, listener);
2.50 + success &= indexer.index(new IndexingContext(getDescriptor().getCacheDir(), build, launcher, listener, addedFiles, removedFiles));
2.51 }
2.52 //XXX:
2.53 File info = new File(Cache.findCache("jackpot30").findCacheRoot(build.getWorkspace().toURI().toURL()), "info");
2.54 @@ -187,6 +203,14 @@
2.55 }
2.56 }
2.57
2.58 + private String stripLeadingSlash(String path) {
2.59 + if (path.length() > 0 && path.charAt(0) == '/') {
2.60 + return path.substring(1);
2.61 + }
2.62 +
2.63 + return path;
2.64 + }
2.65 +
2.66 @Extension // this marker indicates Hudson that this is an implementation of an extension point.
2.67 public static final class DescriptorImpl extends Descriptor<Builder> {
2.68
3.1 --- a/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/JackpotIndexBuilder.java Wed Dec 22 13:43:37 2010 +0100
3.2 +++ b/server/hudson/src/main/java/org/netbeans/modules/jackpot30/hudson/JackpotIndexBuilder.java Mon Dec 27 15:06:57 2010 +0100
3.3 @@ -40,13 +40,7 @@
3.4 package org.netbeans.modules.jackpot30.hudson;
3.5
3.6 import hudson.Extension;
3.7 -import hudson.Launcher;
3.8 import hudson.Proc;
3.9 -import hudson.model.AbstractBuild;
3.10 -import hudson.model.BuildListener;
3.11 -import hudson.scm.ChangeLogSet.AffectedFile;
3.12 -import hudson.scm.ChangeLogSet.Entry;
3.13 -import hudson.scm.EditType;
3.14 import hudson.util.ArgumentListBuilder;
3.15 import java.io.File;
3.16 import java.io.FileOutputStream;
3.17 @@ -55,7 +49,6 @@
3.18 import java.io.Writer;
3.19 import java.net.MalformedURLException;
3.20 import java.net.URL;
3.21 -import java.util.HashSet;
3.22 import java.util.Set;
3.23 import net.sf.json.JSONObject;
3.24 import org.kohsuke.stapler.DataBoundConstructor;
3.25 @@ -75,27 +68,14 @@
3.26 public JackpotIndexBuilder() {}
3.27
3.28 @Override
3.29 - public boolean index(File cacheDir, AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
3.30 - listener.getLogger().println("Jackpot 3.0 indexing:");
3.31 -
3.32 - Set<String> addedFiles = new HashSet<String>();
3.33 - Set<String> removedFiles = new HashSet<String>();
3.34 -
3.35 - for (Entry e : build.getChangeSet()) {
3.36 - for (AffectedFile f : e.getAffectedFiles()) {
3.37 - if (f.getEditType() == EditType.DELETE) {
3.38 - removedFiles.add(f.getPath());
3.39 - } else {
3.40 - addedFiles.add(f.getPath());
3.41 - }
3.42 - }
3.43 - }
3.44 + public boolean index(IndexingContext context) throws IOException, InterruptedException {
3.45 + context.listener.getLogger().println("Jackpot 3.0 indexing:");
3.46
3.47 File a = File.createTempFile("jck30", "");
3.48 File r = File.createTempFile("jck30", "");
3.49
3.50 - dumpToFile(a, addedFiles);
3.51 - dumpToFile(r, removedFiles);
3.52 + dumpToFile(a, context.addedOrModified);
3.53 + dumpToFile(r, context.removed);
3.54
3.55 ArgumentListBuilder args = new ArgumentListBuilder();
3.56
3.57 @@ -105,14 +85,14 @@
3.58 args.add(new File(indexerLocation, "indexer.jar").getAbsolutePath());
3.59 args.add("-store-sources");
3.60 args.add(".");
3.61 - args.add(cacheDir);
3.62 + args.add(context.cacheDir);
3.63 args.add(a.getAbsolutePath());
3.64 args.add(r.getAbsolutePath());
3.65
3.66 - Proc indexer = launcher.launch().pwd(build.getWorkspace())
3.67 - .cmds(args)
3.68 - .stdout(listener)
3.69 - .start();
3.70 + Proc indexer = context.launcher.launch().pwd(context.build.getWorkspace())
3.71 + .cmds(args)
3.72 + .stdout(context.listener)
3.73 + .start();
3.74
3.75 indexer.join();
3.76
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/server/hudson/src/test/java/org/netbeans/modules/jackpot30/hudson/IndexingBuilderTest.java Mon Dec 27 15:06:57 2010 +0100
4.3 @@ -0,0 +1,211 @@
4.4 +/*
4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.6 + *
4.7 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
4.8 + *
4.9 + * The contents of this file are subject to the terms of either the GNU
4.10 + * General Public License Version 2 only ("GPL") or the Common
4.11 + * Development and Distribution License("CDDL") (collectively, the
4.12 + * "License"). You may not use this file except in compliance with the
4.13 + * License. You can obtain a copy of the License at
4.14 + * http://www.netbeans.org/cddl-gplv2.html
4.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
4.16 + * specific language governing permissions and limitations under the
4.17 + * License. When distributing the software, include this License Header
4.18 + * Notice in each file and include the License file at
4.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
4.20 + * particular file as subject to the "Classpath" exception as provided
4.21 + * by Sun in the GPL Version 2 section of the License file that
4.22 + * accompanied this code. If applicable, add the following below the
4.23 + * License Header, with the fields enclosed by brackets [] replaced by
4.24 + * your own identifying information:
4.25 + * "Portions Copyrighted [year] [name of copyright owner]"
4.26 + *
4.27 + * If you wish your version of this file to be governed by only the CDDL
4.28 + * or only the GPL Version 2, indicate your decision by adding
4.29 + * "[Contributor] elects to include this software in this distribution
4.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
4.31 + * single choice of license, a recipient has the option to distribute
4.32 + * your version of this file under either the CDDL, the GPL Version 2 or
4.33 + * to extend the choice of license to its licensees as provided above.
4.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
4.35 + * Version 2 license, then the option applies only if the new code is
4.36 + * made subject to such option by the copyright holder.
4.37 + *
4.38 + * Contributor(s):
4.39 + *
4.40 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
4.41 + */
4.42 +
4.43 +package org.netbeans.modules.jackpot30.hudson;
4.44 +
4.45 +import hudson.FilePath;
4.46 +import hudson.Launcher;
4.47 +import hudson.model.FreeStyleProject;
4.48 +import hudson.model.Hudson;
4.49 +import hudson.scm.SubversionSCM;
4.50 +import hudson.scm.SubversionSCM.ModuleLocation;
4.51 +import hudson.util.ArgumentListBuilder;
4.52 +import hudson.util.StreamTaskListener;
4.53 +import java.io.File;
4.54 +import java.io.FileOutputStream;
4.55 +import java.io.IOException;
4.56 +import java.util.Arrays;
4.57 +import java.util.Collections;
4.58 +import java.util.Set;
4.59 +import org.jvnet.hudson.test.HudsonHomeLoader;
4.60 +import org.jvnet.hudson.test.HudsonTestCase;
4.61 +import static org.junit.Assert.*;
4.62 +import org.netbeans.api.jackpot.hudson.IndexBuilder;
4.63 +import org.xml.sax.SAXException;
4.64 +
4.65 +/**
4.66 + *
4.67 + * @author lahvac
4.68 + */
4.69 +public class IndexingBuilderTest extends HudsonTestCase {
4.70 +
4.71 + public IndexingBuilderTest() {
4.72 + }
4.73 +
4.74 + @Override
4.75 + protected void setUp() throws Exception {
4.76 + super.setUp();
4.77 +
4.78 + checkoutDir = HudsonHomeLoader.NEW.allocate();
4.79 + repositoryDir = HudsonHomeLoader.NEW.allocate();
4.80 + }
4.81 +
4.82 + @Override
4.83 + protected void tearDown() throws Exception {
4.84 + super.tearDown();
4.85 +
4.86 + //XXX: some of the working directories seems to be kept by the testing infra, workarounding:
4.87 + new FilePath(checkoutDir).deleteRecursive();
4.88 + new FilePath(repositoryDir).deleteRecursive();
4.89 + hudson.getRootPath().deleteRecursive();
4.90 + }
4.91 +
4.92 + private File checkoutDir;
4.93 + private File repositoryDir;
4.94 +
4.95 + public void testUpdate() throws Exception {
4.96 + //setup svn repository:
4.97 + String repositoryURL = repositoryDir.toURI().toURL().toExternalForm().replace("file:/", "file:///");
4.98 + runSubversionAdmin("create", repositoryDir.getAbsolutePath());
4.99 + runSubversion("checkout", repositoryURL, ".");
4.100 + createFile("A.java");
4.101 + createFile("B.java");
4.102 + runSubversion("add", "A.java", "B.java");
4.103 + runSubversion("commit", "-m", "initial");
4.104 +
4.105 + FreeStyleProject p = createFreeStyleProject();
4.106 + ModuleLocation mod1 = new ModuleLocation(repositoryURL, null);
4.107 + SubversionSCM scm = new SubversionSCM(Collections.singletonList(mod1), true, null, "", "", "");
4.108 + IndexBuilderImpl indexer = new IndexBuilderImpl();
4.109 + p.setScm(scm);
4.110 + p.getBuildersList().add(new IndexingBuilder(contextPath, Collections.<IndexBuilder>singleton(indexer)));
4.111 +
4.112 + doRunProject(p);
4.113 +
4.114 + assertTrue(indexer.called);
4.115 +
4.116 + runSubversion("remove", "B.java");
4.117 + createFile("C.java");
4.118 + runSubversion("add", "C.java");
4.119 + runSubversion("commit", "-m", "");
4.120 +
4.121 + indexer.called = false;
4.122 + doRunProject(p);
4.123 +
4.124 + assertTrue(indexer.called);
4.125 + assertEquals(Collections.singleton("C.java"), indexer.addedOrModified);
4.126 + assertEquals(Collections.singleton("B.java"), indexer.removed);
4.127 + }
4.128 +
4.129 + public void DISABLEDtestCheckoutIntoSpecifiedDir() throws Exception {
4.130 + //setup svn repository:
4.131 + String repositoryURL = repositoryDir.toURI().toURL().toExternalForm().replace("file:/", "file:///");
4.132 + runSubversionAdmin("create", repositoryDir.getAbsolutePath());
4.133 + runSubversion("checkout", repositoryURL, ".");
4.134 + createFile("A.java");
4.135 + createFile("B.java");
4.136 + runSubversion("add", "A.java", "B.java");
4.137 + runSubversion("commit", "-m", "initial");
4.138 +
4.139 + FreeStyleProject p = createFreeStyleProject();
4.140 + ModuleLocation mod1 = new ModuleLocation(repositoryURL, "repo1");
4.141 + SubversionSCM scm = new SubversionSCM(Collections.singletonList(mod1), true, null, "", "", "");
4.142 + IndexBuilderImpl indexer = new IndexBuilderImpl();
4.143 + p.setScm(scm);
4.144 + p.getBuildersList().add(new IndexingBuilder(contextPath, Collections.<IndexBuilder>singleton(indexer)));
4.145 +
4.146 + doRunProject(p);
4.147 +
4.148 + assertTrue(indexer.called);
4.149 +
4.150 + runSubversion("remove", "B.java");
4.151 + createFile("C.java");
4.152 + runSubversion("add", "C.java");
4.153 + runSubversion("commit", "-m", "");
4.154 +
4.155 + indexer.called = false;
4.156 + doRunProject(p);
4.157 +
4.158 + assertTrue(indexer.called);
4.159 + assertEquals(Arrays.asList(""), indexer.addedOrModified);
4.160 + assertEquals(Arrays.asList(""), indexer.removed);
4.161 + }
4.162 +
4.163 + private void doRunProject(FreeStyleProject p) throws SAXException, IOException, InterruptedException {
4.164 + WebClient w = new WebClient();
4.165 + w.getPage(p, "build?delay=0sec");
4.166 +
4.167 + Thread.sleep(5000);
4.168 +
4.169 + while (p.isBuilding()) {
4.170 + Thread.sleep(100);
4.171 + }
4.172 + }
4.173 +
4.174 + private void runSubversion(String... args) throws IOException, InterruptedException {
4.175 + Launcher.LocalLauncher l = new Launcher.LocalLauncher(new StreamTaskListener(System.err));
4.176 + l.launch().cmds(new ArgumentListBuilder().add("svn").add(args))
4.177 + .pwd(checkoutDir)
4.178 + .start()
4.179 + .join();
4.180 + }
4.181 +
4.182 + private void runSubversionAdmin(String... args) throws IOException, InterruptedException {
4.183 + Launcher.LocalLauncher l = new Launcher.LocalLauncher(new StreamTaskListener(System.err));
4.184 + l.launch().cmds(new ArgumentListBuilder().add("svnadmin").add(args))
4.185 + .pwd(repositoryDir)
4.186 + .start()
4.187 + .join();
4.188 + }
4.189 +
4.190 + private void createFile(String relativePath) throws IOException {
4.191 + File toCreate = new File(checkoutDir, relativePath.replace('/', File.separatorChar));
4.192 +
4.193 + toCreate.getParentFile().mkdirs();
4.194 +
4.195 + new FileOutputStream(toCreate).close();
4.196 + }
4.197 +
4.198 + private static final class IndexBuilderImpl extends IndexBuilder {
4.199 +
4.200 + private boolean called;
4.201 + private Set<String> addedOrModified;
4.202 + private Set<String> removed;
4.203 +
4.204 + @Override
4.205 + public boolean index(IndexingContext context) throws InterruptedException, IOException {
4.206 + addedOrModified = context.addedOrModified;
4.207 + removed = context.removed;
4.208 + called = true;
4.209 + return true;
4.210 + }
4.211 +
4.212 + }
4.213 +
4.214 +}
4.215 \ No newline at end of file