externalFiles = new HashMap<>();
18 | while (parser.next() != XmlPullParser.END_DOCUMENT) {
19 | if (parser.getEventType() == XmlPullParser.START_TAG
20 | && "Element".equalsIgnoreCase(parser.getName())) {
21 | final String location = parser.getAttributeValue("", "location");
22 | final String status = parser.getAttributeValue("", "status");
23 | try {
24 | externalFiles.put(location, new RefTreeExternalFile(location, status));
25 | } catch (NumberFormatException e) {
26 | throw new UnhandledAccurevCommandOutput(e);
27 | }
28 | }
29 | }
30 | return externalFiles;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/ByteArrayStream.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.Closeable;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 |
9 | /** Simple class to capture the output of something, and then allow that output to be read. */
10 | public class ByteArrayStream implements Closeable {
11 |
12 | private final Output mOutputStream = new Output();
13 |
14 | /**
15 | * Gets the {@link ByteArrayOutputStream} to which data can be written.
16 | *
17 | * @return See above.
18 | */
19 | public ByteArrayOutputStream getOutput() {
20 | return mOutputStream;
21 | }
22 |
23 | /**
24 | * Gets an {@link InputStream} that'll contain all the data that was written to {@link
25 | * #getOutput()} thus far.
26 | *
27 | * Note that it does NOT read any data written after this method completes and it is NOT
28 | * thread-safe (if data is being written to when this method gets called, behaviour is undefined).
29 | *
30 | * @return See above.
31 | */
32 | public InputStream getInput() {
33 | return mOutputStream.toInputStream();
34 | }
35 |
36 | public void close() throws IOException {
37 | mOutputStream.reset();
38 | mOutputStream.close();
39 | }
40 |
41 | private static final class Output extends ByteArrayOutputStream {
42 |
43 | /** Returns an {@link InputStream} of our data without copying the data. */
44 | InputStream toInputStream() {
45 | return new ByteArrayInputStream(super.buf, 0, super.count);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/delegates/Relocation.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.delegates;
2 |
3 | import hudson.util.ArgumentListBuilder;
4 | import java.util.List;
5 |
6 | /** @author raymond */
7 | public class Relocation {
8 |
9 | private final List relocationOptions;
10 | private final String newHost;
11 | private final String newPath;
12 | private final String newParent;
13 |
14 | public Relocation(
15 | List relocationOptions, String newHost, String newPath, String newParent) {
16 | this.relocationOptions = relocationOptions;
17 | this.newHost = newHost;
18 | this.newPath = newPath;
19 | this.newParent = newParent;
20 | }
21 |
22 | public boolean isRelocationRequired() {
23 | return !relocationOptions.isEmpty();
24 | }
25 |
26 | public String getNewParent() {
27 | return newParent;
28 | }
29 |
30 | public String getNewPath() {
31 | return newPath;
32 | }
33 |
34 | public String getNewHost() {
35 | return newHost;
36 | }
37 |
38 | public boolean isPopRequired() {
39 | for (RelocationOption relocationOption : relocationOptions) {
40 | if (relocationOption.isPopRequired()) {
41 | return true;
42 | }
43 | }
44 | return false;
45 | }
46 |
47 | public void appendCommands(ArgumentListBuilder relocateCommand) {
48 | for (RelocationOption relocationOption : relocationOptions) {
49 | relocationOption.appendCommand(relocateCommand, this);
50 | }
51 | }
52 |
53 | public interface RelocationOption {
54 |
55 | boolean isPopRequired();
56 |
57 | void appendCommand(ArgumentListBuilder cmd, Relocation relocation);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/ShowDepots.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import hudson.EnvVars;
4 | import hudson.Launcher;
5 | import hudson.model.TaskListener;
6 | import hudson.plugins.accurev.AccurevLauncher;
7 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
8 | import hudson.plugins.accurev.XmlParserFactory;
9 | import hudson.plugins.accurev.parsers.xml.ParseShowDepots;
10 | import hudson.util.ArgumentListBuilder;
11 | import java.io.IOException;
12 | import java.util.List;
13 | import java.util.logging.Logger;
14 | import jenkins.model.Jenkins;
15 | import org.xmlpull.v1.XmlPullParserFactory;
16 |
17 | public class ShowDepots extends Command {
18 |
19 | public static List getDepots( //
20 | final AccurevServer server, final Logger descriptorLogger) throws IOException {
21 |
22 | Jenkins jenkins = Jenkins.get();
23 | TaskListener listener = TaskListener.NULL;
24 | Launcher launcher = jenkins.createLauncher(listener);
25 | EnvVars accurevEnv = new EnvVars();
26 |
27 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
28 | cmd.add("show");
29 | addServer(cmd, server);
30 | cmd.add("-fx");
31 | cmd.add("depots");
32 |
33 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
34 | if (parser == null) {
35 | throw new IOException("No XML Parser");
36 | }
37 | return AccurevLauncher.runCommand(
38 | "show depots command",
39 | "",
40 | launcher,
41 | cmd,
42 | null,
43 | accurevEnv,
44 | jenkins.getRootPath(),
45 | listener,
46 | descriptorLogger,
47 | parser,
48 | new ParseShowDepots(),
49 | null);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/DetermineRemoteHostname.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import hudson.remoting.Callable;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.net.InetAddress;
7 | import java.net.UnknownHostException;
8 | import org.jenkinsci.remoting.RoleChecker;
9 |
10 | public class DetermineRemoteHostname
11 | implements Callable {
12 |
13 | private final String path;
14 | private static final long serialVersionUID = 1L;
15 |
16 | public DetermineRemoteHostname(String path) {
17 | this.path = path;
18 | }
19 |
20 | /** {@inheritDoc} */
21 | public RemoteWorkspaceDetails call() throws UnknownHostException {
22 | InetAddress addr = InetAddress.getLocalHost();
23 | File f = new File(path);
24 | String path;
25 | try {
26 | path = f.getCanonicalPath();
27 | } catch (IOException e) {
28 | path = f.getAbsolutePath();
29 | }
30 | String ipPattern =
31 | "^(([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))\\.){3}([01]?[0-9]?[0-9]|2([0-4][0-9]|5[0-5]))$";
32 | String hostName = addr.getCanonicalHostName(); // try full hostname
33 | if (hostName.matches(ipPattern)) {
34 | hostName = addr.getHostName(); // try hostname
35 | }
36 | // Accurev does not accept IP addresses so we are going to throw an error.
37 | if (hostName.matches(ipPattern)) {
38 | throw new UnknownHostException("Found IP, but need HostName, ensure proper FQDN.");
39 | }
40 | return new RemoteWorkspaceDetails(hostName, path);
41 | }
42 |
43 | @Override
44 | public void checkRoles(RoleChecker roleChecker) throws SecurityException {
45 | // TODO: Implement Role check
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/AccurevChangeLogSet.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import hudson.model.Run;
4 | import hudson.scm.ChangeLogSet;
5 | import java.util.Collection;
6 | import java.util.Collections;
7 | import java.util.Iterator;
8 | import java.util.List;
9 | import org.kohsuke.stapler.export.Exported;
10 | import org.kohsuke.stapler.export.ExportedBean;
11 |
12 | /**
13 | * Created by IntelliJ IDEA.
14 | *
15 | * @author connollys
16 | * @since 10-Oct-2007 13:12:40
17 | */
18 | @ExportedBean(defaultVisibility = 999)
19 | public final class AccurevChangeLogSet extends ChangeLogSet {
20 |
21 | private final List transactions;
22 |
23 | AccurevChangeLogSet(Run build, List transactions) {
24 | // TODO: Implement RepositoryBrowser?
25 | super(build, null);
26 | if (transactions == null) {
27 | throw new NullPointerException("Cannot have a null transaction list");
28 | }
29 | this.transactions = Collections.unmodifiableList(transactions);
30 | for (AccurevTransaction transaction : transactions) {
31 | transaction.setParent(this);
32 | }
33 | }
34 |
35 | public boolean isEmptySet() {
36 | return transactions.isEmpty();
37 | }
38 |
39 | public Iterator iterator() {
40 | return transactions.iterator();
41 | }
42 |
43 | public Collection getLogs() {
44 | return transactions;
45 | }
46 |
47 | public java.lang.Object[] toArray() {
48 | if (transactions == null) {
49 | return new java.lang.Object[0];
50 | }
51 |
52 | return transactions.toArray();
53 | }
54 |
55 | @Exported
56 | public String getKind() {
57 | return "accurev";
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/parsers/output/ParseInfoToLoginName.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.parsers.output;
2 |
3 | import hudson.plugins.accurev.AccurevLauncher.ICmdOutputParser;
4 | import hudson.plugins.accurev.AccurevLauncher.UnhandledAccurevCommandOutput;
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.InputStreamReader;
9 | import java.io.Reader;
10 | import java.nio.charset.Charset;
11 |
12 | public final class ParseInfoToLoginName implements ICmdOutputParser {
13 |
14 | public String parse(InputStream cmdOutput, Void context)
15 | throws UnhandledAccurevCommandOutput, IOException {
16 | final String usernameHeading = "Principal:";
17 | final String controlCharsOrSpaceRegex = "[ \\x00-\\x1F\\x7F]+";
18 | final Reader stringReader = new InputStreamReader(cmdOutput, Charset.defaultCharset());
19 | try (BufferedReader reader = new BufferedReader(stringReader)) {
20 | String line;
21 | while ((line = reader.readLine()) != null) {
22 | if (line.contains("not logged in")) {
23 | return null;
24 | }
25 | final String[] parts = line.split(controlCharsOrSpaceRegex);
26 | for (int i = 0; i < parts.length; i++) {
27 | final String part = parts[i];
28 | if (usernameHeading.equals(part)) {
29 | if ((i + 1) < parts.length) {
30 | return parts[i + 1]; // returns username
31 | }
32 | }
33 | }
34 | }
35 | }
36 | throw new UnhandledAccurevCommandOutput(
37 | "Output did not contain "
38 | + usernameHeading
39 | + " "
40 | + controlCharsOrSpaceRegex
41 | + " ");
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/hudson/plugins/accurev/ConfigurationAsCodeTest.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import static org.hamcrest.MatcherAssert.assertThat;
4 | import static org.hamcrest.core.Is.is;
5 |
6 | import io.jenkins.plugins.casc.ConfigurationAsCode;
7 | import io.jenkins.plugins.casc.ConfiguratorException;
8 | import org.junit.Rule;
9 | import org.junit.Test;
10 | import org.jvnet.hudson.test.JenkinsRule;
11 |
12 | public class ConfigurationAsCodeTest {
13 |
14 | @Rule public JenkinsRule r = new JenkinsRule();
15 |
16 | @Test
17 | public void shouldSupportConfigurationAsCode() throws Exception {
18 | configureJenkins("accurev.yaml");
19 |
20 | AccurevSCM.AccurevSCMDescriptor desc = AccurevSCM.configuration();
21 |
22 | assertThat(desc.isPollOnMaster(), is(true));
23 | assertThat(desc.getServers().size(), is(1));
24 |
25 | AccurevSCM.AccurevServer server1 = desc.getServers().get(0);
26 |
27 | assertThat(server1.getName(), is("testserver1"));
28 | assertThat(server1.getHost(), is("testhost"));
29 | assertThat(server1.getPort(), is(1234));
30 | assertThat(server1.getCredentialsId(), is("abc123"));
31 | assertThat(server1.isSyncOperations(), is(true));
32 | assertThat(server1.isMinimiseLogins(), is(true));
33 | assertThat(server1.isUseNonexpiringLogin(), is(true));
34 | assertThat(server1.isUseRestrictedShowStreams(), is(true));
35 | assertThat(server1.isUseColor(), is(true));
36 | assertThat(server1.isUsePromoteListen(), is(true));
37 | assertThat(server1.isServerDisabled(), is(true));
38 | }
39 |
40 | private void configureJenkins(final String fileName) throws ConfiguratorException {
41 | ConfigurationAsCode.get()
42 | .configure(ConfigurationAsCodeTest.class.getResource(fileName).toString());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/webapp/help/project/subpath.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Some projects only use a portion of the stream or reference tree and, in these instances, it is
4 | not necessary to
5 | check out the entire contents of the repository, such as
6 | when you are accessing, for example, a large remote repository to build a sub-module. In such
7 | cases, it may be
8 | useful to set up a sub-path. If you specify a sub-path, the
9 | plugin makes a "best effort" to ensure that only the sub-path is populated. This means that the
10 | files within the
11 | sub-path will be fetched, at least, although side-effects
12 | may result in files from other locations being fetched as well.
13 |
14 |
15 |
16 | Directories and files must be specified in a comma-separated list and can use relative
17 | pathnames. For example,
18 | you could use:
19 |
20 |
21 |
22 | src/com/my-company/main/my-file.java,src/com/*,src/com/webapp/my-file2.xml
23 |
24 |
25 | where "src" is the immediate sub-folder under your stream or reference tree.
26 |
27 |
28 | NOTES:
29 |
30 |
31 | The Sub-path option only works if you configure it before the first build is
32 | triggered.
33 |
34 | If you specify a sub-path and you also select Poll SCM in the Build Triggers
35 | section of the
36 | Jenkins configuration page, but you do not specify any Filter
37 | for Poll SCM files or directories, then the sub-path files and directories are used as
38 | the filter
39 | for polling. In this case, changes made to elements in the
40 | sub-path will trigger a build in Jenkins.
41 |
42 |
43 |
44 | .
45 |
46 |
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Jenkins AccuRev Plugin
2 |
3 | [](https://ci.jenkins.io/job/Plugins/job/accurev-plugin/job/master/)
4 | [](https://plugins.jenkins.io/accurev)
5 | [](https://github.com/jenkinsci/accurev-plugin/releases/latest)
6 | [](https://plugins.jenkins.io/accurev)
7 |
8 | This plugin allows you to use [AccuRev](https://www.microfocus.com/en-us/products/accurev/overview) as a SCM.
9 |
10 | ## Adopt this plugin
11 |
12 | This plugin is up for adoption, it needs an activate maintainer who actively uses AccuRev.
13 |
14 | ## Bug Reports
15 |
16 | File bug reports [here](http://issues.jenkins-ci.org/secure/IssueNavigator.jspa?mode=hide&reset=true&jqlQuery=project+%3D+JENKINS+AND+status+in+%28Open%2C+%22In+Progress%22%2C+Reopened%29+AND+component+%3D+%27accurev-plugin%27)
17 |
18 | ## Development
19 |
20 | Start the local Jenkins instance:
21 |
22 | ```bash
23 | mvn hpi:run
24 | ```
25 |
26 | ### How to install
27 |
28 | Run
29 |
30 | ```bash
31 | mvn clean package
32 | ```
33 |
34 | to create the plugin .hpi file.
35 |
36 |
37 | To install:
38 |
39 | 1. copy the resulting ./target/accurev.hpi file to the $JENKINS_HOME/plugins directory. Don't forget to restart Jenkins afterwards.
40 |
41 | 2. or use the plugin management console (http://example.com:8080/pluginManager/advanced) to upload the hpi file. You have to restart Jenkins in order to find the pluing in the installed plugins list.
42 |
43 | ## Plugin releases
44 |
45 | ```bash
46 | mvn release:prepare release:perform -B
47 | ```
48 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/parsers/xml/ParseShowWorkspaces.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.parsers.xml;
2 |
3 | import hudson.plugins.accurev.AccurevLauncher.ICmdOutputXmlParser;
4 | import hudson.plugins.accurev.AccurevLauncher.UnhandledAccurevCommandOutput;
5 | import hudson.plugins.accurev.AccurevWorkspace;
6 | import java.io.IOException;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 | import org.xmlpull.v1.XmlPullParser;
10 | import org.xmlpull.v1.XmlPullParserException;
11 |
12 | public final class ParseShowWorkspaces
13 | implements ICmdOutputXmlParser, Void> {
14 |
15 | public Map parse(XmlPullParser parser, Void context)
16 | throws UnhandledAccurevCommandOutput, IOException, XmlPullParserException {
17 | final Map workspaces = new HashMap<>();
18 | while (parser.next() != XmlPullParser.END_DOCUMENT) {
19 | if (parser.getEventType() == XmlPullParser.START_TAG
20 | && "Element".equalsIgnoreCase(parser.getName())) {
21 | final String name = parser.getAttributeValue("", "Name");
22 | final String storage = parser.getAttributeValue("", "Storage");
23 | final String host = parser.getAttributeValue("", "Host");
24 | final String streamNumber = parser.getAttributeValue("", "Stream");
25 | final String depot = parser.getAttributeValue("", "depot");
26 | try {
27 | final Long streamNumberOrNull = streamNumber == null ? null : Long.valueOf(streamNumber);
28 | workspaces.put(
29 | name, new AccurevWorkspace(depot, streamNumberOrNull, name, host, storage));
30 | } catch (NumberFormatException e) {
31 | throw new UnhandledAccurevCommandOutput(e);
32 | }
33 | }
34 | }
35 | return workspaces;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/hudson/plugins/accurev/CheckForChangesTest.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import static org.junit.Assert.assertFalse;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.util.ArrayList;
7 | import java.util.Collection;
8 | import org.junit.Test;
9 |
10 | /** Initialized by josep on 29-01-2017. */
11 | public class CheckForChangesTest {
12 |
13 | @Test
14 | public void testPathWithMatch() {
15 | Collection serverPaths = new ArrayList<>();
16 | serverPaths.add("/home/joseph/test/hi-lib-dal-mongo/somefile.java");
17 | Collection filters = new ArrayList<>();
18 | filters.add("*/hi-lib-dal-mongo/*");
19 | assertTrue(CheckForChanges.changesMatchFilter(serverPaths, filters));
20 | }
21 |
22 | @Test
23 | public void testPathMatcher() {
24 | assertTrue(CheckForChanges.pathMatcher("/home/joseph/some.java", "*.java"));
25 | assertTrue(
26 | CheckForChanges.pathMatcher(
27 | "/home/joseph/test/hi-lib-dal-mongo/test/somefile.java",
28 | "*/joseph/*/hi-lib-dal-mongo*"));
29 | }
30 |
31 | @Test
32 | public void testStringWithoutWildcard() {
33 | Collection serverPaths = new ArrayList<>();
34 | serverPaths.add("/home/joseph/test/hi-lib-dal-mongo/somefile.java");
35 | Collection filters = new ArrayList<>();
36 | filters.add("hi-lib-dal");
37 | assertFalse(CheckForChanges.changesMatchFilter(serverPaths, filters));
38 | }
39 |
40 | @Test
41 | public void testStringWithFileWildcard() {
42 | Collection serverPaths = new ArrayList<>();
43 | serverPaths.add("/home/joseph/test/hi-lib-dal-mongo/somefile.java");
44 | Collection filters = new ArrayList<>();
45 | filters.add("*.java");
46 | assertTrue(CheckForChanges.changesMatchFilter(serverPaths, filters));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/parsers/xml/ParseShowReftrees.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.parsers.xml;
2 |
3 | import hudson.plugins.accurev.AccurevLauncher.ICmdOutputXmlParser;
4 | import hudson.plugins.accurev.AccurevLauncher.UnhandledAccurevCommandOutput;
5 | import hudson.plugins.accurev.AccurevReferenceTree;
6 | import java.io.IOException;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 | import org.xmlpull.v1.XmlPullParser;
10 | import org.xmlpull.v1.XmlPullParserException;
11 |
12 | public class ParseShowReftrees
13 | implements ICmdOutputXmlParser, Void> {
14 |
15 | public Map parse(XmlPullParser parser, Void context)
16 | throws UnhandledAccurevCommandOutput, IOException, XmlPullParserException {
17 | final Map reftrees = new HashMap<>();
18 | while (parser.next() != XmlPullParser.END_DOCUMENT) {
19 | if (parser.getEventType() == XmlPullParser.START_TAG
20 | && "Element".equalsIgnoreCase(parser.getName())) {
21 | final String name = parser.getAttributeValue("", "Name");
22 | final String storage = parser.getAttributeValue("", "Storage");
23 | final String host = parser.getAttributeValue("", "Host");
24 | final String streamNumber = parser.getAttributeValue("", "Stream");
25 | final String depot = parser.getAttributeValue("", "depot");
26 | try {
27 | final Long streamNumberOrNull = streamNumber == null ? null : Long.valueOf(streamNumber);
28 | reftrees.put(
29 | name, new AccurevReferenceTree(depot, streamNumberOrNull, name, host, storage));
30 | } catch (NumberFormatException e) {
31 | throw new UnhandledAccurevCommandOutput(e);
32 | }
33 | }
34 | }
35 | return reftrees;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/jenkins/plugins/accurev/util/AccurevUtils.java:
--------------------------------------------------------------------------------
1 | package jenkins.plugins.accurev.util;
2 |
3 | import static org.apache.commons.lang.time.DateUtils.MILLIS_PER_SECOND;
4 |
5 | import edu.umd.cs.findbugs.annotations.CheckForNull;
6 | import hudson.FilePath;
7 | import hudson.model.Computer;
8 | import hudson.model.Node;
9 | import java.util.Date;
10 | import jenkins.model.Jenkins;
11 |
12 | public class AccurevUtils {
13 |
14 | public static String cleanAccurevPath(String str) {
15 | return str.replace("\\", "/").replaceFirst("^/[.]/", "");
16 | }
17 |
18 | @CheckForNull
19 | public static Node workspaceToNode(FilePath workspace) {
20 | Computer computer = workspace.toComputer();
21 | Node node = null;
22 | if (null != computer) {
23 | node = computer.getNode();
24 | }
25 | return null != node ? node : Jenkins.get();
26 | }
27 |
28 | public static String getRootPath(FilePath workspace) {
29 | Node n = workspaceToNode(workspace);
30 | String path = null;
31 | FilePath filePath = null;
32 | if (null != n) {
33 | filePath = n.getRootPath();
34 | }
35 | if (null != filePath) {
36 | path = filePath.getRemote();
37 | }
38 | return path;
39 | }
40 |
41 | /**
42 | * Converts an Accurev timestamp into a {@link Date}
43 | *
44 | * @param timeInSeconds The accurev timestamp.
45 | * @return A {@link Date} set to the time for the accurev timestamp.
46 | */
47 | public static Date convertAccurevTimestamp(@CheckForNull String timeInSeconds) {
48 | if (timeInSeconds == null) {
49 | return null;
50 | }
51 | try {
52 | final long time = Long.parseLong(timeInSeconds);
53 | final long date = time * MILLIS_PER_SECOND;
54 | return new Date(date);
55 | } catch (NumberFormatException e) {
56 | return null;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/SetProperty.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import hudson.EnvVars;
4 | import hudson.FilePath;
5 | import hudson.Launcher;
6 | import hudson.model.TaskListener;
7 | import hudson.plugins.accurev.AccurevLauncher;
8 | import hudson.plugins.accurev.AccurevSCM;
9 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
10 | import hudson.util.ArgumentListBuilder;
11 | import java.io.IOException;
12 | import java.util.logging.Logger;
13 |
14 | public class SetProperty extends Command {
15 |
16 | private static final Logger logger = Logger.getLogger(SetProperty.class.getName());
17 |
18 | public static void setproperty(
19 | final AccurevSCM scm,
20 | final FilePath workspace, //
21 | final TaskListener listener, //
22 | final Launcher launcher,
23 | final EnvVars accurevEnv,
24 | final AccurevServer server,
25 | final String streamOrWorkspaceName,
26 | final String colorCode,
27 | final String propertyName)
28 | throws IOException {
29 |
30 | String propertyValue =
31 | "";
32 |
33 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
34 | cmd.add("setproperty");
35 | Command.addServer(cmd, server);
36 | cmd.add("-s");
37 | cmd.add(streamOrWorkspaceName);
38 | cmd.add("-r");
39 | cmd.add(propertyName);
40 | cmd.add(propertyValue);
41 | boolean runCommand =
42 | AccurevLauncher.runCommand(
43 | "setproperty background color",
44 | scm.getAccurevTool(),
45 | launcher,
46 | cmd,
47 | scm.getOptionalLock(workspace),
48 | accurevEnv,
49 | workspace,
50 | listener,
51 | logger,
52 | true);
53 | if (!runCommand) {
54 | throw new IOException("Command failed");
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/resources/hudson/plugins/accurev/AccurevSCM/AccurevServer/config.groovy:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.AccurevSCM.AccurevServer
2 |
3 | import lib.CredentialsTagLib
4 | import lib.FormTagLib
5 |
6 | def f = namespace(FormTagLib)
7 | def c = namespace(CredentialsTagLib)
8 |
9 | f.entry(field: "name", title: _("Name")) {
10 | f.textbox()
11 | }
12 | f.entry(field: "host", title: _("Host")) {
13 | f.textbox()
14 | }
15 | f.entry(field: "port", title: _("Port")) {
16 | f.number(clazz: "number", min: 0, max: 65535, step: 1, default: 5050)
17 | }
18 | f.entry(field: "credentialsId", title: _("Credentials")) {
19 | c.select()
20 | }
21 | f.entry() {
22 | f.validateButton(method: "test", title: "Test Connection", with: "name,host,port,credentialsId")
23 | }
24 | f.advanced {
25 | f.entry(field: "syncOperations", title: _("Synchronize AccuRev CLI Operations"), help: "/plugin/accurev/help/sync-operations.html") {
26 | f.checkbox()
27 | }
28 | f.entry(field: "minimiseLogins", title: _("Minimise AccuRev Login Operations"), help: "/plugin/accurev/help/minimise-login-operations.html") {
29 | f.checkbox()
30 | }
31 | f.entry(field: "useNonexpiringLogin", title: _("Use Non-expiring Login"), help: "/plugin/accurev/help/use-nonexpiring-login.html") {
32 | f.checkbox()
33 | }
34 | f.entry(field: "useRestrictedShowStreams", title: _("Show one stream at a time"), help: "/plugin/accurev/help/use-restricted-show-streams.html") {
35 | f.checkbox()
36 | }
37 | f.entry(field: "useColor", title: _("Enable reset Color"), help: "/plugin/accurev/help/use-color.html") {
38 | f.checkbox()
39 | }
40 | f.entry(field: "usePromoteListen", title: _("Enable Post Promote Listener"), help: "/plugin/accurev/help/use-promote-listen.html") {
41 | f.checkbox()
42 | }
43 | f.entry(field: "uuid", title: _("ID")) {
44 | f.textbox(disabled: true)
45 | }
46 | f.entry(field: "serverDisabled", title: "Disable Plugin for this server ", help: "/plugin/accurev/help/server-disable.html") {
47 | f.checkbox()
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/webapp/help/project/reftree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | By default, AccuRev Plug-in for Jenkins checks out the latest changes without using a reference
4 | tree. When not
5 | using a reference tree, AccuRev Plug-in for Jenkins uses the
6 | accurev pop -R command to extract all the files. However, there may be situations
7 | when the use of a
8 | reference tree is preferred, such as when you want to use
9 | the latest versions of files that you do not intend to modify. You can think of a reference tree
10 | as a read-only
11 | portal to the AccuRev data repository.
12 |
13 |
14 |
If the Use Reference Tree check box is marked, AccuRev Plug-in for Jenkins attempts to
15 | use the reference
16 | tree specified in the Reference Tree text box. (You
17 | must create a reference tree in AccuRev before you can specify it here.) AccuRev Plug-in for
18 | Jenkins manages the
19 | process of migrating the reference tree to the appropriate
20 | build machine and relocating the reference tree to use the correct location. Note that these
21 | changes are
22 | recorded in the AccuRev repository.
23 |
24 | When using a reference tree, the following AccuRev commands are used:
25 |
26 |
27 |
28 | accurev show refs confirms that the reference tree is valid and has the correct
29 | parent stream.
30 |
31 | accurev chref is run if the reference tree is in the wrong directory or on the
32 | wrong machine.
33 | (Optional)
34 |
35 | accurev update refreshes the reference tree. If the update fails, AccuRev
36 | Plug-in for Jenkins
37 | uses the accurev update -9 command to update the
38 | reference tree.
39 |
40 | accurev pop -O -R ensures that all files are populated and that the reference
41 | tree always
42 | contains the fresh update.
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/AccurevReferenceTree.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import java.io.Serializable;
4 |
5 | public class AccurevReferenceTree implements Serializable {
6 |
7 | private final String depot;
8 | private final Long streamNumber;
9 | private final String name;
10 | private final String host;
11 | private final String storage;
12 | private AccurevStream stream = null;
13 | private static final long serialVersionUID = 1L;
14 |
15 | public AccurevReferenceTree(
16 | String depot, Long streamNumber, String name, String host, String storage) {
17 | this.depot = depot;
18 | this.streamNumber = streamNumber;
19 | this.name = name;
20 | this.host = host;
21 | this.storage = storage;
22 | }
23 |
24 | /**
25 | * Getter for property 'depot'.
26 | *
27 | * @return Value for property 'depot'.
28 | */
29 | public String getDepot() {
30 | return depot;
31 | }
32 |
33 | /**
34 | * Getter for property 'streamNumber'.
35 | *
36 | * @return Value for property 'streamNumber'.
37 | */
38 | public Long getStreamNumber() {
39 | return streamNumber;
40 | }
41 |
42 | /**
43 | * Getter for property 'name'.
44 | *
45 | * @return Value for property 'name'.
46 | */
47 | public String getName() {
48 | return name;
49 | }
50 |
51 | /**
52 | * Getter for property 'host'.
53 | *
54 | * @return Value for property 'host'.
55 | */
56 | public String getHost() {
57 | return host;
58 | }
59 |
60 | /**
61 | * Getter for property 'storage'.
62 | *
63 | * @return Value for property 'storage'.
64 | */
65 | public String getStorage() {
66 | return storage;
67 | }
68 |
69 | /**
70 | * Getter for property 'stream'.
71 | *
72 | * @return Value for property 'stream'.
73 | */
74 | public AccurevStream getStream() {
75 | return stream;
76 | }
77 |
78 | /**
79 | * Setter for property 'stream'.
80 | *
81 | * @param stream Value to set for property 'stream'.
82 | */
83 | public void setStream(AccurevStream stream) {
84 | this.stream = stream;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/AccurevWorkspace.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * Created by IntelliJ IDEA.
7 | *
8 | * @author connollys
9 | * @since 03-Dec-2007 13:17:39
10 | */
11 | public class AccurevWorkspace implements Serializable {
12 |
13 | private final String depot;
14 | private final Long streamNumber;
15 | private final String name;
16 | private final String host;
17 | private final String storage;
18 | private AccurevStream stream = null;
19 | private static final long serialVersionUID = 1L;
20 |
21 | public AccurevWorkspace(
22 | String depot, Long streamNumber, String name, String host, String storage) {
23 | this.depot = depot;
24 | this.streamNumber = streamNumber;
25 | this.name = name;
26 | this.host = host;
27 | this.storage = storage;
28 | }
29 |
30 | /**
31 | * Getter for property 'depot'.
32 | *
33 | * @return Value for property 'depot'.
34 | */
35 | public String getDepot() {
36 | return depot;
37 | }
38 |
39 | /**
40 | * Getter for property 'streamNumber'.
41 | *
42 | * @return Value for property 'streamNumber'.
43 | */
44 | public Long getStreamNumber() {
45 | return streamNumber;
46 | }
47 |
48 | /**
49 | * Getter for property 'name'.
50 | *
51 | * @return Value for property 'name'.
52 | */
53 | public String getName() {
54 | return name;
55 | }
56 |
57 | /**
58 | * Getter for property 'host'.
59 | *
60 | * @return Value for property 'host'.
61 | */
62 | public String getHost() {
63 | return host;
64 | }
65 |
66 | /**
67 | * Getter for property 'storage'.
68 | *
69 | * @return Value for property 'storage'.
70 | */
71 | public String getStorage() {
72 | return storage;
73 | }
74 |
75 | /**
76 | * Getter for property 'stream'.
77 | *
78 | * @return Value for property 'stream'.
79 | */
80 | public AccurevStream getStream() {
81 | return stream;
82 | }
83 |
84 | /**
85 | * Setter for property 'stream'.
86 | *
87 | * @param stream Value to set for property 'stream'.
88 | */
89 | public void setStream(AccurevStream stream) {
90 | this.stream = stream;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/parsers/output/ParsePopulate.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.parsers.output;
2 |
3 | import hudson.plugins.accurev.AccurevLauncher.ICmdOutputParser;
4 | import hudson.plugins.accurev.AccurevLauncher.UnhandledAccurevCommandOutput;
5 | import java.io.BufferedReader;
6 | import java.io.BufferedWriter;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.InputStreamReader;
10 | import java.io.OutputStream;
11 | import java.io.OutputStreamWriter;
12 | import java.io.Reader;
13 | import java.io.Writer;
14 | import java.nio.charset.Charset;
15 |
16 | /**
17 | * Filters the output of the populate command and just shows a summary of the output. Helps prevent
18 | * build logs being clogged up with the checkout.
19 | */
20 | public final class ParsePopulate implements ICmdOutputParser {
21 |
22 | public Boolean parse(InputStream cmdOutput, OutputStream streamToCopyOutputTo)
23 | throws UnhandledAccurevCommandOutput, IOException {
24 | final String lineStartDirectory = "Creating dir:";
25 | final String lineStartElement = "Populating element";
26 | int countOfDirectories = 0;
27 | int countOfElements = 0;
28 | final Reader stringReader = new InputStreamReader(cmdOutput, Charset.defaultCharset());
29 | final Writer stringWriter =
30 | new OutputStreamWriter(streamToCopyOutputTo, Charset.defaultCharset());
31 | final BufferedWriter lineWriter = new BufferedWriter(stringWriter);
32 | try (BufferedReader reader = new BufferedReader(stringReader)) {
33 | String line;
34 | while ((line = reader.readLine()) != null) {
35 | if (line.startsWith(lineStartElement)) {
36 | countOfElements++;
37 | } else if (line.startsWith(lineStartDirectory)) {
38 | countOfDirectories++;
39 | } else {
40 | lineWriter.write(line);
41 | lineWriter.newLine();
42 | }
43 | }
44 | final String msg =
45 | "Populated " + countOfElements + " elements and " + countOfDirectories + " directories.";
46 | streamToCopyOutputTo.write(msg.getBytes(Charset.defaultCharset()));
47 | } finally {
48 | lineWriter.flush();
49 | }
50 | return Boolean.TRUE;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/FilesCmd.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import hudson.EnvVars;
4 | import hudson.FilePath;
5 | import hudson.Launcher;
6 | import hudson.model.TaskListener;
7 | import hudson.plugins.accurev.AccurevElement;
8 | import hudson.plugins.accurev.AccurevLauncher;
9 | import hudson.plugins.accurev.AccurevSCM;
10 | import hudson.plugins.accurev.XmlParserFactory;
11 | import hudson.plugins.accurev.parsers.xml.ParseFiles;
12 | import hudson.util.ArgumentListBuilder;
13 | import java.io.IOException;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.logging.Logger;
17 | import org.xmlpull.v1.XmlPullParserFactory;
18 |
19 | public class FilesCmd extends Command {
20 |
21 | private static final Logger logger = Logger.getLogger(Login.class.getName());
22 |
23 | public static List checkFiles(
24 | final AccurevSCM scm,
25 | final AccurevSCM.AccurevServer server,
26 | final EnvVars accurevEnv,
27 | final FilePath workspace,
28 | final TaskListener listener,
29 | final Launcher launcher,
30 | FilePath file)
31 | throws IOException {
32 | final String commandDescription = "files command";
33 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
34 | cmd.add("files");
35 | addServer(cmd, server);
36 | cmd.add("-fx");
37 | cmd.add("-s", scm.getStream());
38 | cmd.add("-l", file.getRemote());
39 |
40 | // returns username
41 | final ArrayList list = new ArrayList<>(1);
42 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
43 | if (parser == null) {
44 | throw new IOException("No XML Parser");
45 | }
46 | final Boolean filesFound =
47 | AccurevLauncher.runCommand(
48 | commandDescription,
49 | scm.getAccurevTool(),
50 | launcher,
51 | cmd,
52 | scm.getOptionalLock(workspace),
53 | accurevEnv,
54 | workspace,
55 | listener,
56 | logger,
57 | parser,
58 | new ParseFiles(),
59 | list);
60 | if (filesFound == null) {
61 | throw new IOException("FilesCmd command failed.");
62 | }
63 | return list;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/webapp/help/project/workspace.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | By default, this plugin checks out the latest changes without using a workspace. This removes
4 | the need to
5 | manually create a workspace for each project, and removes the need for the plugin to make
6 | transactions
7 | while moving the workspace from slave to slave as the build migrates from slave to slave.
8 |
9 |
10 |
11 | However, there may be situations when the use of a workspace is preferred. If you want to use a
12 | workspace,
13 | select this option and enter the name of an existing workspace in the Workspace field.
14 | The plugin can
15 | manage
16 | migrating the workspace to the appropriate build machine and re-parenting the workspace to use
17 | the correct
18 | parent
19 | stream (Jenkins considers the Stream field value as the parent stream). Note that
20 | workspace changes
21 | (accurev chws) are logged as AccuRev transactions.
22 |
23 |
24 |
When not using a workspace, the following AccuRev commands will be used:
25 |
26 | accurev pop -O -R . to extract all the files. Note: this command will not work
27 | if the
28 | directory that the files are being extracted to is the child of an active AccuRev workspace.
29 |
30 |
31 |
When using a workspace, the following AccuRev commands are used:
32 |
33 | accurev show wspaces to validate that the workspace is valid and has the
34 | correct parent stream
35 |
36 |
37 |
If the workspace needs to be relocated or if the host machine needs to be updated, the
38 | following AccuRev commands
39 | are also used:
40 |
41 | accurev chws
42 | accurev update -9
43 | accurev pop -O -R .
44 |
45 |
Otherwise, the following commands are run:
46 |
47 | accurev chws (if re-parenting is required)
48 | accurev update
49 |
50 |
Note: If you decide to stop using an AccuRev workspace after having run a build, you
51 | must manually move
52 | the AccuRev workspace directory.
53 |
54 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/XmlParserFactory.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import java.io.IOException;
4 | import java.util.Map;
5 | import java.util.WeakHashMap;
6 | import java.util.logging.Logger;
7 | import org.xmlpull.v1.XmlPullParser;
8 | import org.xmlpull.v1.XmlPullParserException;
9 | import org.xmlpull.v1.XmlPullParserFactory;
10 |
11 | /** Utility class that provides {@link XmlPullParserFactory}s. */
12 | public class XmlParserFactory {
13 |
14 | private static final Logger logger = Logger.getLogger(AccurevSCM.class.getName());
15 | private static final Map PARSER_FACTORY_CACHE =
16 | new WeakHashMap<>(1);
17 |
18 | /**
19 | * Gets a new {@link XmlPullParser} configured for parsing Accurev XML files.
20 | *
21 | * @return a new {@link XmlPullParser} configured for parsing Accurev XML files.
22 | * @throws XmlPullParserException when things go wrong/
23 | * @throws IOException Handle it above
24 | */
25 | static XmlPullParser newParser() throws XmlPullParserException, IOException {
26 | XmlPullParserFactory factory = null;
27 | XmlPullParser parser = null;
28 | if (null != getFactory()) {
29 | factory = getFactory();
30 | }
31 | if (null != factory) {
32 | parser = factory.newPullParser();
33 | }
34 | return parser;
35 | }
36 |
37 | /**
38 | * Gets a new {@link XmlPullParserFactory} configured for parsing Accurev XML files.
39 | *
40 | * @return a new {@link XmlPullParserFactory} configured for parsing Accurev XML files, or
41 | * null if things go wrong.
42 | * @throws IOException Handle it above
43 | */
44 | public static XmlPullParserFactory getFactory() throws IOException {
45 | synchronized (PARSER_FACTORY_CACHE) {
46 | final XmlPullParserFactory existingFactory =
47 | PARSER_FACTORY_CACHE.get(XmlPullParserFactory.class);
48 | if (existingFactory != null) {
49 | return existingFactory;
50 | }
51 | XmlPullParserFactory newFactory;
52 | try {
53 | newFactory = XmlPullParserFactory.newInstance();
54 | } catch (XmlPullParserException ex) {
55 | AccurevLauncher.logException(
56 | "Unable to create new " + XmlPullParserFactory.class.getSimpleName(), ex, logger, null);
57 | return null;
58 | }
59 | newFactory.setNamespaceAware(false);
60 | newFactory.setValidating(false);
61 | PARSER_FACTORY_CACHE.put(XmlPullParserFactory.class, newFactory);
62 | return newFactory;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/resources/hudson/plugins/accurev/AccurevChangeLogSet/index.jelly:
--------------------------------------------------------------------------------
1 |
4 |
5 |
7 |
8 |
9 | No changes
10 |
11 |
12 | Summary
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | AccuWork Issue Number - ${cs.issueNum}
30 |
31 |
32 |
33 | AccuWork Issue Number -
34 | ${cs.issueNum}
35 |
36 |
37 |
38 |
39 |
40 |
Transaction
41 |
42 | ${cs.id}
43 |
44 | ${cs.id}
45 |
46 |
47 | by
48 | ${cs.author}
49 | :
50 |
51 |
52 | ${cs.msg}
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | ${p}
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/delegates/SnapshotDelegate.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.delegates;
2 |
3 | import hudson.EnvVars;
4 | import hudson.model.Run;
5 | import hudson.plugins.accurev.AccurevLauncher;
6 | import hudson.plugins.accurev.AccurevSCM;
7 | import hudson.plugins.accurev.cmd.Command;
8 | import hudson.util.ArgumentListBuilder;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.util.logging.Logger;
12 | import org.apache.commons.lang.StringUtils;
13 |
14 | /** @author raymond */
15 | public class SnapshotDelegate extends StreamDelegate {
16 |
17 | private static final Logger logger = Logger.getLogger(SnapshotDelegate.class.getName());
18 | private static final String DEFAULT_SNAPSHOT_NAME_FORMAT = "${JOB_NAME}_${BUILD_NUMBER}";
19 | private String snapshotName;
20 |
21 | public SnapshotDelegate(AccurevSCM scm) {
22 | super(scm);
23 | }
24 |
25 | private String calculateSnapshotName(final Run, ?> build)
26 | throws IOException, InterruptedException {
27 | String snapshotNameFormat = scm.getSnapshotNameFormat();
28 | final String actualFormat =
29 | StringUtils.isBlank(snapshotNameFormat)
30 | ? DEFAULT_SNAPSHOT_NAME_FORMAT
31 | : snapshotNameFormat.trim();
32 | final EnvVars environment = build.getEnvironment(listener);
33 | return environment.expand(actualFormat);
34 | }
35 |
36 | @Override
37 | protected boolean checkout(Run, ?> build, File changeLogFile)
38 | throws IOException, InterruptedException {
39 | snapshotName = calculateSnapshotName(build);
40 | listener.getLogger().println("Creating snapshot: " + snapshotName + "...");
41 | build.getEnvironment(listener).put("ACCUREV_SNAPSHOT", snapshotName);
42 | // snapshot command: accurev mksnap -H -s -b -t now
43 | final ArgumentListBuilder mksnapcmd = new ArgumentListBuilder();
44 | mksnapcmd.add("mksnap");
45 | Command.addServer(mksnapcmd, server);
46 | mksnapcmd.add("-s");
47 | mksnapcmd.add(snapshotName);
48 | mksnapcmd.add("-b");
49 | mksnapcmd.add(localStream);
50 | mksnapcmd.add("-t");
51 | mksnapcmd.add("now");
52 | if (!AccurevLauncher.runCommand(
53 | "Create snapshot command",
54 | scm.getAccurevTool(),
55 | launcher,
56 | mksnapcmd,
57 | scm.getOptionalLock(jenkinsWorkspace),
58 | accurevEnv,
59 | jenkinsWorkspace,
60 | listener,
61 | logger,
62 | true)) {
63 | return false;
64 | }
65 | listener.getLogger().println("Snapshot created successfully.");
66 | return true;
67 | }
68 |
69 | @Override
70 | protected boolean isSteamColorEnabled() {
71 | return false;
72 | }
73 |
74 | @Override
75 | protected String getPopulateFromMessage() {
76 | return "from snapshot";
77 | }
78 |
79 | @Override
80 | protected String getPopulateStream() {
81 | return snapshotName;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/XmlConsolidateStreamChangeLog.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.WeakHashMap;
10 | import java.util.logging.Logger;
11 | import javax.xml.stream.XMLOutputFactory;
12 | import javax.xml.stream.XMLStreamException;
13 | import javax.xml.stream.XMLStreamWriter;
14 |
15 | /** */
16 | public class XmlConsolidateStreamChangeLog {
17 |
18 | private static final Logger logger = Logger.getLogger(AccurevSCM.class.getName());
19 | private static final Map, XMLOutputFactory> OUTPUT_FACTORY_CACHE =
20 | new WeakHashMap<>(1);
21 |
22 | static XMLOutputFactory getFactory() {
23 | synchronized (OUTPUT_FACTORY_CACHE) {
24 | final XMLOutputFactory existingFactory = OUTPUT_FACTORY_CACHE.get(XMLOutputFactory.class);
25 | if (existingFactory != null) {
26 | return existingFactory;
27 | }
28 | XMLOutputFactory newFactory = XMLOutputFactory.newFactory();
29 | OUTPUT_FACTORY_CACHE.put(XMLOutputFactory.class, newFactory);
30 | return newFactory;
31 | }
32 | }
33 |
34 | public static File getStreamChangeLogFile(File changelogFile, AccurevStream stream) {
35 | File dir = changelogFile.getParentFile();
36 | return new File(dir, stream.getName() + "_" + changelogFile.getName());
37 | }
38 |
39 | public static File getUpdateChangeLogFile(File changelogFile) {
40 | File dir = changelogFile.getParentFile();
41 | return new File(dir, "update_" + changelogFile.getName());
42 | }
43 |
44 | public static void createChangeLog(
45 | List streamFiles, File changeLogFile, String updateFile) throws IOException {
46 | try (FileOutputStream changeLogStream = new FileOutputStream(changeLogFile)) {
47 | XMLOutputFactory outputFactory = getFactory();
48 | XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(changeLogStream);
49 | streamWriter.writeStartDocument();
50 | streamWriter.writeStartElement("ChangeLogs");
51 | if (updateFile != null) {
52 | streamWriter.writeStartElement("UpdateLog");
53 | streamWriter.writeCharacters(updateFile);
54 | streamWriter.writeEndElement();
55 | }
56 | for (String streamFile : streamFiles) {
57 | streamWriter.writeStartElement("ChangeLog");
58 | streamWriter.writeCharacters(streamFile);
59 | streamWriter.writeEndElement();
60 | }
61 | streamWriter.writeEndElement();
62 | streamWriter.writeEndDocument();
63 | } catch (FileNotFoundException | XMLStreamException ex) {
64 | AccurevLauncher.logException(
65 | "Unable to create consolidated changelog "
66 | + XmlConsolidateStreamChangeLog.class.getSimpleName(),
67 | ex,
68 | logger,
69 | null);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/java/jenkins/plugins/accurev/AccurevToolTest.java:
--------------------------------------------------------------------------------
1 | package jenkins.plugins.accurev;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import hudson.EnvVars;
6 | import hudson.model.Node;
7 | import hudson.model.TaskListener;
8 | import hudson.slaves.DumbSlave;
9 | import hudson.tools.CommandInstaller;
10 | import hudson.tools.InstallSourceProperty;
11 | import hudson.tools.ToolInstallation;
12 | import hudson.tools.ToolInstaller;
13 | import hudson.tools.ToolProperty;
14 | import hudson.util.StreamTaskListener;
15 | import java.io.IOException;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import org.junit.Before;
19 | import org.junit.Test;
20 | import org.jvnet.hudson.test.JenkinsRule;
21 |
22 | /** Initialized by josep on 22-01-2017. */
23 | public class AccurevToolTest {
24 |
25 | @org.junit.Rule public JenkinsRule j = new JenkinsRule();
26 |
27 | private AccurevTool accurevTool;
28 |
29 | public static AccurevTool createTool(String name) throws IOException {
30 | List installers = new ArrayList();
31 | installers.add(new CommandInstaller(null, "accurev", "./"));
32 |
33 | List> properties =
34 | new ArrayList>();
35 | properties.add(new InstallSourceProperty(installers));
36 |
37 | return new AccurevTool(name, "./", properties);
38 | }
39 |
40 | @Before
41 | public void setUp() throws Exception {
42 | AccurevTool.onLoaded();
43 | accurevTool = AccurevTool.getDefaultInstallation();
44 | }
45 |
46 | @Test
47 | public void testForNode() throws Exception {
48 | DumbSlave slave = j.createSlave();
49 | slave.setMode(Node.Mode.EXCLUSIVE);
50 | TaskListener log = StreamTaskListener.fromStdout();
51 | AccurevTool newTool = accurevTool.forNode(slave, log);
52 | assertEquals(accurevTool.getHome(), newTool.getHome());
53 | }
54 |
55 | @Test
56 | public void testForEnvironment() throws Exception {
57 | EnvVars environment = new EnvVars();
58 | AccurevTool newTool = accurevTool.forEnvironment(environment);
59 | assertEquals(accurevTool.getHome(), newTool.getHome());
60 | }
61 |
62 | @Test
63 | public void testGetDescriptor() throws Exception {
64 | AccurevTool.DescriptorImpl descriptor = accurevTool.getDescriptor();
65 | assertEquals("AccuRev", descriptor.getDisplayName());
66 | }
67 |
68 | @Test
69 | public void testGetInstallationFromDescriptor() throws Exception {
70 | AccurevTool.DescriptorImpl descriptor = accurevTool.getDescriptor();
71 | assertEquals(null, descriptor.getInstallation(""));
72 | assertEquals(null, descriptor.getInstallation("not-a-valid-accurev-install"));
73 | }
74 |
75 | @Test
76 | public void testGetDefaultInstallationFromDescriptor() throws Exception {
77 | AccurevTool newTool = AccurevTool.getDefaultInstallation();
78 | assertEquals(accurevTool.getHome(), newTool.getHome());
79 | assertEquals(accurevTool.getName(), newTool.getName());
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/parsers/xml/ParseShowStreams.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.parsers.xml;
2 |
3 | import static jenkins.plugins.accurev.util.AccurevUtils.convertAccurevTimestamp;
4 |
5 | import hudson.plugins.accurev.AccurevLauncher.ICmdOutputXmlParser;
6 | import hudson.plugins.accurev.AccurevLauncher.UnhandledAccurevCommandOutput;
7 | import hudson.plugins.accurev.AccurevStream;
8 | import hudson.plugins.accurev.AccurevStream.StreamType;
9 | import java.io.IOException;
10 | import java.util.Date;
11 | import java.util.HashMap;
12 | import java.util.Map;
13 | import org.xmlpull.v1.XmlPullParser;
14 | import org.xmlpull.v1.XmlPullParserException;
15 |
16 | public final class ParseShowStreams
17 | implements ICmdOutputXmlParser, String> {
18 |
19 | public Map parse(XmlPullParser parser, String depot)
20 | throws UnhandledAccurevCommandOutput, IOException, XmlPullParserException {
21 | final Map streams = new HashMap<>();
22 | while (parser.next() != XmlPullParser.END_DOCUMENT) {
23 | if (parser.getEventType() == XmlPullParser.START_TAG
24 | && "stream".equalsIgnoreCase(parser.getName())) {
25 | final String streamName = parser.getAttributeValue("", "name");
26 |
27 | final String streamNumberStr = parser.getAttributeValue("", "streamNumber");
28 | final String basisStreamName = parser.getAttributeValue("", "basis");
29 | final String basisStreamNumberStr = parser.getAttributeValue("", "basisStreamNumber");
30 | final String streamTypeStr = parser.getAttributeValue("", "type");
31 | final String streamIsDynamic = parser.getAttributeValue("", "isDynamic");
32 | final String streamTimeString = parser.getAttributeValue("", "time");
33 | final Date streamTime =
34 | streamTimeString == null ? null : convertAccurevTimestamp(streamTimeString);
35 | final String streamStartTimeString = parser.getAttributeValue("", "startTime");
36 | final Date streamStartTime =
37 | streamTimeString == null ? null : convertAccurevTimestamp(streamStartTimeString);
38 | try {
39 | final Long streamNumber = streamNumberStr == null ? null : Long.valueOf(streamNumberStr);
40 | final Long basisStreamNumber =
41 | basisStreamNumberStr == null ? null : Long.valueOf(basisStreamNumberStr);
42 | final StreamType streamType = AccurevStream.StreamType.parseStreamType(streamTypeStr);
43 | final boolean isDynamic =
44 | streamIsDynamic != null && Boolean.parseBoolean(streamIsDynamic);
45 | final AccurevStream stream =
46 | new AccurevStream( //
47 | streamName, //
48 | streamNumber, //
49 | depot, //
50 | basisStreamName, //
51 | basisStreamNumber, //
52 | isDynamic, //
53 | streamType, //
54 | streamTime, //
55 | streamStartTime);
56 | streams.put(streamName, stream);
57 | } catch (NumberFormatException e) {
58 | throw new UnhandledAccurevCommandOutput(e);
59 | }
60 | }
61 | }
62 | return streams;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/jenkins/plugins/accurev/AccurevPlugin.java:
--------------------------------------------------------------------------------
1 | package jenkins.plugins.accurev;
2 |
3 | import static hudson.init.InitMilestone.COMPLETED;
4 | import static hudson.init.InitMilestone.EXTENSIONS_AUGMENTED;
5 | import static hudson.init.InitMilestone.JOB_LOADED;
6 |
7 | import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
8 | import hudson.init.Initializer;
9 | import hudson.model.Project;
10 | import hudson.plugins.accurev.AccurevSCM;
11 | import hudson.plugins.accurev.AccurevSCM.AccurevSCMDescriptor;
12 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
13 | import java.util.logging.Logger;
14 | import jenkins.model.Jenkins;
15 | import jenkins.plugins.accurev.util.UUIDUtils;
16 |
17 | /** Initialized by josp on 21/09/16. */
18 | @SuppressWarnings("unused") // Used for initialization/migration purpose
19 | public class AccurevPlugin {
20 |
21 | private static final Logger LOGGER = Logger.getLogger(AccurevPlugin.class.getName());
22 |
23 | /**
24 | * We need ensure that migrator will run after jobs are loaded Launches migration after plugin and
25 | * jobs already initialized. Expected milestone: @Initializer(after = JOB_LOADED)
26 | *
27 | * @throws Exception Exceptions
28 | */
29 | @Initializer(after = JOB_LOADED, before = COMPLETED)
30 | public static void migrateJobsToServerUUID() throws Exception {
31 | final Jenkins jenkins = Jenkins.get();
32 | boolean changed = false;
33 | AccurevSCMDescriptor descriptor = jenkins.getDescriptorByType(AccurevSCMDescriptor.class);
34 | for (Project, ?> p : jenkins.getAllItems(Project.class)) {
35 | if (p.getScm() instanceof AccurevSCM) {
36 | AccurevSCM scm = (AccurevSCM) p.getScm();
37 | String serverUUID = scm.getServerUUID();
38 | if (UUIDUtils.isNotValid(serverUUID) || descriptor.getServer(serverUUID) == null) {
39 | AccurevServer server = descriptor.getServer(scm.getServerName());
40 | if (server == null) {
41 | LOGGER.warning(
42 | "No server found with that name, Project: "
43 | + p.getName()
44 | + " Server Name: "
45 | + scm.getServerName());
46 | } else {
47 | changed = true;
48 | String uuid = server.getUuid();
49 | scm.setServerUUID(uuid);
50 | p.save();
51 | }
52 | }
53 | }
54 | }
55 | if (changed) {
56 | descriptor.save();
57 | }
58 | }
59 |
60 | /**
61 | * We need ensure that migrator will after Extensions are augmented Launches migration if servers
62 | * still uses username and password Expected milestone: @Initializer(after = EXTENSIONS_AUGMENTED)
63 | *
64 | * @throws Exception Exceptions
65 | */
66 | @Initializer(after = EXTENSIONS_AUGMENTED)
67 | public static void migrateServersToCredentials() throws Exception {
68 | boolean changed = false;
69 | AccurevSCMDescriptor descriptor = AccurevSCM.configuration();
70 | boolean migratedCredentials = false;
71 | for (AccurevServer server : descriptor.getServers()) {
72 | if (server.migrateCredentials()) {
73 | changed = true;
74 | }
75 | }
76 | if (changed) {
77 | descriptor.save();
78 | SystemCredentialsProvider.getInstance().save();
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/test/java/hudson/plugins/accurev/MigrateIDAndCredentialTest.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.assertNull;
6 | import static org.junit.Assert.assertTrue;
7 |
8 | import com.cloudbees.plugins.credentials.CredentialsMatchers;
9 | import com.cloudbees.plugins.credentials.CredentialsProvider;
10 | import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
11 | import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
12 | import hudson.model.FreeStyleProject;
13 | import hudson.plugins.accurev.AccurevSCM.AccurevSCMDescriptor;
14 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
15 | import hudson.security.ACL;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import jenkins.model.Jenkins;
19 | import jenkins.plugins.accurev.AccurevPlugin;
20 | import org.apache.commons.lang.StringUtils;
21 | import org.junit.Before;
22 | import org.junit.Test;
23 | import org.jvnet.hudson.test.JenkinsRule;
24 |
25 | @SuppressWarnings("deprecation")
26 | public class MigrateIDAndCredentialTest {
27 |
28 | @org.junit.Rule public JenkinsRule j = new JenkinsRule();
29 |
30 | private AccurevSCMDescriptor descriptor;
31 | private AccurevSCM scm;
32 |
33 | @Before
34 | public void setUp() throws Exception {
35 | AccurevServer server = new AccurevServer(null, "test", "localhost");
36 | server.setUsername("bob");
37 | server.setPassword("OBF:1rwf1x1b1rwf");
38 | scm = new AccurevSCM(server.getName(), "test", "test");
39 | scm.setServerName("test");
40 | FreeStyleProject accurevTest = j.createFreeStyleProject("accurevTest");
41 | accurevTest.setScm(scm);
42 | descriptor = scm.getDescriptor();
43 | List servers = new ArrayList<>();
44 | servers.add(server);
45 | descriptor.setServers(servers);
46 | }
47 |
48 | @Test
49 | public void testMigrateCredential() throws Exception {
50 | AccurevServer server = AccurevSCM.configuration().getServers().get(0);
51 | boolean migrated = server.migrateCredentials();
52 | StandardUsernamePasswordCredentials credentials =
53 | CredentialsMatchers.firstOrNull(
54 | CredentialsProvider.lookupCredentials(
55 | StandardUsernamePasswordCredentials.class,
56 | Jenkins.getInstance(),
57 | ACL.SYSTEM,
58 | URIRequirementBuilder.fromUri("").withHostnamePort("localhost", 5050).build()),
59 | CredentialsMatchers.withUsername("bob"));
60 | assertTrue(migrated);
61 | assertNotNull(server.getCredentialsId());
62 | assertNotNull(server.getCredentials());
63 | assertEquals(server.getCredentials().getUsername(), credentials.getUsername());
64 | assertEquals(server.getCredentials().getPassword(), credentials.getPassword());
65 | assertNull(server.username);
66 | assertNull(server.password);
67 | }
68 |
69 | @Test
70 | public void testMigrateToServerUUID() throws Exception {
71 | AccurevPlugin.migrateJobsToServerUUID();
72 | AccurevServer server = AccurevSCM.configuration().getServers().get(0);
73 | assertTrue(StringUtils.equals(server.getUuid(), scm.getServerUUID()));
74 | assertNotNull(descriptor.getServer(scm.getServerUUID()));
75 | assertNotNull(scm.getServer());
76 | assertEquals(descriptor.getServer(scm.getServerUUID()), scm.getServer());
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/PopulateCmd.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import hudson.EnvVars;
4 | import hudson.FilePath;
5 | import hudson.Launcher;
6 | import hudson.model.TaskListener;
7 | import hudson.plugins.accurev.AccurevLauncher;
8 | import hudson.plugins.accurev.AccurevSCM;
9 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
10 | import hudson.plugins.accurev.parsers.output.ParsePopulate;
11 | import hudson.util.ArgumentListBuilder;
12 | import java.io.IOException;
13 | import java.util.Date;
14 | import java.util.StringTokenizer;
15 | import java.util.logging.Logger;
16 | import org.apache.commons.lang.StringUtils;
17 |
18 | public class PopulateCmd extends Command {
19 |
20 | private static final Logger logger = Logger.getLogger(PopulateCmd.class.getName());
21 |
22 | private Date _startDateOfPopulate;
23 |
24 | /** @return Date */
25 | public Date get_startDateOfPopulate() {
26 | return (Date) _startDateOfPopulate.clone();
27 | }
28 |
29 | /**
30 | * @param scm Accurev SCm
31 | * @param launcher launcher
32 | * @param listener listener
33 | * @param server server
34 | * @param streamName stream Name
35 | * @param overwrite overwrite
36 | * @param fromMessage from Messge
37 | * @param workspace Accurev Workspace
38 | * @param accurevEnv Accurev Environment
39 | * @param files list of files to be populated
40 | * @return boolean
41 | * @throws IOException Handle it above
42 | */
43 | public boolean populate(
44 | AccurevSCM scm,
45 | Launcher launcher,
46 | TaskListener listener,
47 | AccurevServer server,
48 | String streamName,
49 | boolean overwrite,
50 | String fromMessage,
51 | FilePath workspace,
52 | EnvVars accurevEnv,
53 | FilePath files)
54 | throws IOException {
55 | listener.getLogger().println("Populating " + fromMessage + "...");
56 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
57 | cmd.add("pop");
58 | addServer(cmd, server);
59 |
60 | if (streamName != null) {
61 | cmd.add("-v");
62 | cmd.add(streamName);
63 |
64 | if (scm.getSubPathOnly()) {
65 | cmd.add("-D");
66 | }
67 | }
68 |
69 | cmd.add("-L");
70 | cmd.add(workspace.getRemote());
71 |
72 | // Add the file containing list to be populated
73 | if (files != null) {
74 | cmd.add("-l");
75 | cmd.add(files.getRemote());
76 | }
77 |
78 | if (overwrite) {
79 | cmd.add("-O");
80 | }
81 |
82 | cmd.add("-R");
83 | if (StringUtils.isBlank(scm.getSubPath())) {
84 | cmd.add(".");
85 | } else {
86 | final StringTokenizer st = new StringTokenizer(scm.getSubPath(), ",");
87 | while (st.hasMoreElements()) {
88 | String path = st.nextToken().trim();
89 | path = path.replace("*", "");
90 | cmd.add(path);
91 | }
92 | }
93 | _startDateOfPopulate = new Date();
94 | final Boolean success =
95 | AccurevLauncher.runCommand(
96 | "Populate " + fromMessage + " command",
97 | scm.getAccurevTool(),
98 | launcher,
99 | cmd,
100 | scm.getOptionalLock(workspace),
101 | accurevEnv,
102 | workspace,
103 | listener,
104 | logger,
105 | new ParsePopulate(),
106 | listener.getLogger());
107 | if (success == null || !success) {
108 | return false;
109 | }
110 | listener.getLogger().println("Populate completed successfully.");
111 | return true;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/AccurevMode.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import hudson.plugins.accurev.delegates.AbstractModeDelegate;
4 | import hudson.plugins.accurev.delegates.ReftreeDelegate;
5 | import hudson.plugins.accurev.delegates.SnapshotDelegate;
6 | import hudson.plugins.accurev.delegates.StreamDelegate;
7 | import hudson.plugins.accurev.delegates.WorkspaceDelegate;
8 |
9 | /** Determines the delegate used for building */
10 | public enum AccurevMode {
11 | WORKSPACE(true) {
12 | @Override
13 | protected AbstractModeDelegate createDelegate(AccurevSCM accurevSCM) {
14 | return new WorkspaceDelegate(accurevSCM);
15 | }
16 |
17 | @Override
18 | protected boolean isMode(AccurevSCM accurevSCM) {
19 | return "wspace".equals(accurevSCM.getWspaceORreftree());
20 | }
21 |
22 | @Override
23 | public boolean isWorkspace() {
24 | return true;
25 | }
26 | },
27 | REF_TREE(true) {
28 | @Override
29 | protected AbstractModeDelegate createDelegate(AccurevSCM accurevSCM) {
30 | return new ReftreeDelegate(accurevSCM);
31 | }
32 |
33 | @Override
34 | protected boolean isMode(AccurevSCM accurevSCM) {
35 | return "reftree".equals(accurevSCM.getWspaceORreftree());
36 | }
37 |
38 | @Override
39 | public boolean isReftree() {
40 | return true;
41 | }
42 | },
43 | SNAPSHOT(false) {
44 | @Override
45 | protected AbstractModeDelegate createDelegate(AccurevSCM accurevSCM) {
46 | return new SnapshotDelegate(accurevSCM);
47 | }
48 |
49 | @Override
50 | protected boolean isMode(AccurevSCM accurevSCM) {
51 | return !WORKSPACE.isMode(accurevSCM)
52 | && !REF_TREE.isMode(accurevSCM)
53 | && accurevSCM.isUseSnapshot();
54 | }
55 |
56 | public boolean isNoWorkspaceOrRefTree() {
57 | return true;
58 | }
59 | },
60 | STREAM(false) {
61 | @Override
62 | protected AbstractModeDelegate createDelegate(AccurevSCM accurevSCM) {
63 | return new StreamDelegate(accurevSCM);
64 | }
65 |
66 | @Override
67 | protected boolean isMode(AccurevSCM accurevSCM) {
68 | return !WORKSPACE.isMode(accurevSCM)
69 | && !REF_TREE.isMode(accurevSCM)
70 | && !accurevSCM.isUseSnapshot();
71 | }
72 |
73 | @Override
74 | public boolean isNoWorkspaceOrRefTree() {
75 | return true;
76 | }
77 | };
78 |
79 | private final boolean requiresWorkspace;
80 |
81 | AccurevMode(boolean requiresWorkspace) {
82 | this.requiresWorkspace = requiresWorkspace;
83 | }
84 |
85 | public static AbstractModeDelegate findDelegate(AccurevSCM accurevSCM) {
86 | AccurevMode accurevMode = findMode(accurevSCM);
87 | return accurevMode.createDelegate(accurevSCM);
88 | }
89 |
90 | public static AccurevMode findMode(AccurevSCM accurevSCM) {
91 | AccurevMode retVal = null;
92 | for (AccurevMode accurevMode : values()) {
93 | if (accurevMode.isMode(accurevSCM)) {
94 | retVal = accurevMode;
95 | break;
96 | }
97 | }
98 | return retVal;
99 | }
100 |
101 | public boolean isRequiresWorkspace() {
102 | return requiresWorkspace;
103 | }
104 |
105 | public boolean isWorkspace() {
106 | return false;
107 | }
108 |
109 | public boolean isReftree() {
110 | return false;
111 | }
112 |
113 | public boolean isNoWorkspaceOrRefTree() {
114 | return false;
115 | }
116 |
117 | protected abstract boolean isMode(AccurevSCM accurevSCM);
118 |
119 | protected abstract AbstractModeDelegate createDelegate(AccurevSCM accurevSCM);
120 | }
121 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/parsers/xml/ParseHistory.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.parsers.xml;
2 |
3 | import static jenkins.plugins.accurev.util.AccurevUtils.convertAccurevTimestamp;
4 |
5 | import hudson.plugins.accurev.AccurevLauncher.ICmdOutputXmlParser;
6 | import hudson.plugins.accurev.AccurevLauncher.UnhandledAccurevCommandOutput;
7 | import hudson.plugins.accurev.AccurevTransaction;
8 | import java.io.IOException;
9 | import java.util.List;
10 | import jenkins.plugins.accurev.util.AccurevUtils;
11 | import org.xmlpull.v1.XmlPullParser;
12 | import org.xmlpull.v1.XmlPullParserException;
13 |
14 | public final class ParseHistory implements ICmdOutputXmlParser> {
15 |
16 | public Boolean parse(XmlPullParser parser, List context)
17 | throws UnhandledAccurevCommandOutput, IOException, XmlPullParserException {
18 | AccurevTransaction resultTransaction = null;
19 | while (parser.next() != XmlPullParser.END_DOCUMENT) {
20 | if (parser.getEventType() == XmlPullParser.START_TAG) {
21 | if ("transaction".equalsIgnoreCase(parser.getName())) {
22 | resultTransaction = new AccurevTransaction();
23 | // parse transaction-values
24 | resultTransaction.setId((parser.getAttributeValue("", "id")));
25 | resultTransaction.setAction(parser.getAttributeValue("", "type"));
26 | resultTransaction.setDate(convertAccurevTimestamp(parser.getAttributeValue("", "time")));
27 | resultTransaction.setUser(parser.getAttributeValue("", "user"));
28 | } else if ("comment".equalsIgnoreCase(parser.getName()) && resultTransaction != null) {
29 | // parse comments
30 | resultTransaction.setMsg(parser.nextText());
31 | } else if ("version".equalsIgnoreCase(parser.getName()) && resultTransaction != null) {
32 | // parse path & convert it to standard format
33 | String path = parser.getAttributeValue("", "path");
34 | if (path != null) {
35 | path = AccurevUtils.cleanAccurevPath(path);
36 | }
37 | resultTransaction.addAffectedPath(path);
38 | }
39 | }
40 | }
41 | context.add(resultTransaction);
42 | return resultTransaction != null;
43 | }
44 |
45 | public Boolean parseAll(XmlPullParser parser, List context)
46 | throws IOException, XmlPullParserException {
47 | AccurevTransaction resultTransaction = null;
48 | while (parser.next() != XmlPullParser.END_DOCUMENT) {
49 | if (parser.getEventType() == XmlPullParser.START_TAG) {
50 | if ("transaction".equalsIgnoreCase(parser.getName())) {
51 | resultTransaction = new AccurevTransaction();
52 | // parse transaction-values
53 | resultTransaction.setId(parser.getAttributeValue("", "id"));
54 | resultTransaction.setAction(parser.getAttributeValue("", "type"));
55 | resultTransaction.setDate(
56 | AccurevUtils.convertAccurevTimestamp(parser.getAttributeValue("", "time")));
57 | resultTransaction.setUser(parser.getAttributeValue("", "user"));
58 | } else if ("comment".equalsIgnoreCase(parser.getName()) && resultTransaction != null) {
59 | // parse comments
60 | resultTransaction.setMsg(parser.nextText());
61 | } else if ("version".equalsIgnoreCase(parser.getName()) && resultTransaction != null) {
62 | // parse path & convert it to standard format
63 | String path = parser.getAttributeValue("", "path");
64 | if (path != null) path = AccurevUtils.cleanAccurevPath(path);
65 | resultTransaction.addAffectedPath(path);
66 | }
67 | } else if (parser.getEventType() == XmlPullParser.END_TAG) {
68 | if ("transaction".equalsIgnoreCase(parser.getName()) && resultTransaction != null) {
69 | // a transaction parsed
70 | context.add(resultTransaction);
71 | resultTransaction = null;
72 | }
73 | }
74 | }
75 | return Boolean.valueOf((context != null));
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.jenkins-ci.plugins
6 | plugin
7 | 4.75
8 |
9 |
10 |
11 | accurev
12 | hpi
13 | ${revision}${changelist}
14 | Jenkins AccuRev plugin
15 | This plugin allows you to use AccuRev as a SCM.
16 | https://github.com/jenkinsci/accurev-plugin
17 |
18 | 0.7.25
19 | -SNAPSHOT
20 | 2.387.3
21 | Max
22 | Low
23 |
24 |
25 |
26 |
27 | casz
28 | Joseph Petersen
29 |
30 |
31 |
32 |
33 |
34 | repo.jenkins-ci.org
35 | https://repo.jenkins-ci.org/public/
36 |
37 |
38 |
39 |
40 |
41 |
42 | io.jenkins.tools.bom
43 | bom-2.387.x
44 | 2543.vfb_1a_5fb_9496d
45 | import
46 | pom
47 |
48 |
49 |
50 |
51 |
52 |
53 | repo.jenkins-ci.org
54 | https://repo.jenkins-ci.org/public/
55 |
56 |
57 |
58 |
59 | io.jenkins.plugins
60 | commons-lang3-api
61 |
62 |
63 | org.jenkins-ci.plugins
64 | credentials
65 |
66 |
67 | junit
68 | junit
69 | test
70 |
71 |
72 | org.mockito
73 | mockito-core
74 | test
75 |
76 |
77 | io.jenkins
78 | configuration-as-code
79 | test
80 |
81 |
82 |
83 | org.apache.commons
84 | commons-lang3
85 |
86 |
87 |
88 |
89 |
90 |
91 | scm:git:https://github.com/jenkinsci/accurev-plugin.git
92 | scm:git:git@github.com:jenkinsci/accurev-plugin.git
93 | https://github.com/jenkinsci/accurev-plugin
94 | ${scmTag}
95 |
96 |
97 |
98 |
99 |
100 | com.coveo
101 | fmt-maven-plugin
102 | 2.5.1
103 |
104 |
105 |
106 | format
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | The MIT license
117 | https://www.opensource.org/licenses/mit-license.php
118 | repo
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/delegates/StreamDelegate.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.delegates;
2 |
3 | import hudson.model.Job;
4 | import hudson.model.Run;
5 | import hudson.plugins.accurev.AccurevLauncher;
6 | import hudson.plugins.accurev.AccurevSCM;
7 | import hudson.plugins.accurev.AccurevStream;
8 | import hudson.plugins.accurev.CheckForChanges;
9 | import hudson.plugins.accurev.cmd.ShowStreams;
10 | import hudson.plugins.accurev.parsers.output.ParseAccuRevVersion;
11 | import hudson.scm.PollingResult;
12 | import hudson.util.ArgumentListBuilder;
13 | import java.io.File;
14 | import java.io.IOException;
15 | import java.util.Date;
16 | import java.util.Map;
17 | import java.util.logging.Logger;
18 |
19 | /** @author raymond */
20 | public class StreamDelegate extends AbstractModeDelegate {
21 |
22 | private static final Logger logger = Logger.getLogger(StreamDelegate.class.getName());
23 |
24 | public StreamDelegate(AccurevSCM scm) {
25 | super(scm);
26 | }
27 |
28 | @Override
29 | protected boolean checkout(Run, ?> build, File changeLogFile)
30 | throws IOException, InterruptedException {
31 | return true;
32 | }
33 |
34 | @Override
35 | protected String getPopulateFromMessage() {
36 | return "from stream";
37 | }
38 |
39 | @Override
40 | protected String getPopulateStream() {
41 | return localStream;
42 | }
43 |
44 | @Override
45 | protected boolean isSteamColorEnabled() {
46 | return true;
47 | }
48 |
49 | @Override
50 | protected String getStreamColorStream() {
51 | return localStream;
52 | }
53 |
54 | @Override
55 | protected String getStreamColor() {
56 | return "#FFFFFF";
57 | }
58 |
59 | @Override
60 | protected PollingResult checkForChanges(Job, ?> project)
61 | throws IOException, InterruptedException {
62 | final Run, ?> lastBuild = project.getLastBuild();
63 | if (lastBuild == null) {
64 | listener.getLogger().println("Project has never been built");
65 | return PollingResult.BUILD_NOW;
66 | }
67 | final Date buildDate = lastBuild.getTimestamp().getTime();
68 | try {
69 | localStream = scm.getPollingStream(project, listener);
70 | } catch (IllegalArgumentException ex) {
71 | listener.getLogger().println(ex.getMessage());
72 | return PollingResult.NO_CHANGES;
73 | }
74 | final Map streams =
75 | ShowStreams.getStreams(
76 | scm, localStream, server, accurevEnv, jenkinsWorkspace, listener, launcher);
77 | if (streams == null) {
78 | listener
79 | .getLogger()
80 | .println("Could not retrieve any Streams from AccuRev, please check credentials");
81 | return PollingResult.NO_CHANGES;
82 | }
83 | AccurevStream stream = streams.get(localStream);
84 |
85 | if (stream == null) {
86 | listener
87 | .getLogger()
88 | .println("Tried to find '" + localStream + "' Stream, could not found it.");
89 | return PollingResult.NO_CHANGES;
90 | }
91 | // command to get version of accurev
92 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
93 | String ACCUREV_VERSION =
94 | AccurevLauncher.runCommand(
95 | "Accurev version command",
96 | scm.getAccurevTool(),
97 | launcher,
98 | cmd,
99 | null,
100 | accurevEnv,
101 | jenkinsWorkspace,
102 | listener,
103 | logger,
104 | new ParseAccuRevVersion(),
105 | null);
106 | listener
107 | .getLogger()
108 | .println( //
109 | "Accurev Client Version: " + ACCUREV_VERSION);
110 | int version = Integer.parseInt(ACCUREV_VERSION.substring(0, ACCUREV_VERSION.indexOf(".")));
111 | if (version < 7) {
112 | listener
113 | .getLogger()
114 | .println( //
115 | "Upgrade AccuRev Client for improved performance");
116 | }
117 | // There may be changes in a parent stream that we need to factor in.
118 | do {
119 | if (CheckForChanges.checkStreamForChanges(
120 | server,
121 | accurevEnv,
122 | jenkinsWorkspace,
123 | listener,
124 | launcher,
125 | stream,
126 | buildDate,
127 | logger,
128 | scm,
129 | version)) {
130 | return PollingResult.BUILD_NOW;
131 | }
132 | stream = stream.getParent();
133 | } while (stream != null
134 | && stream.isReceivingChangesFromParent()
135 | && !scm.isIgnoreStreamParent());
136 | return PollingResult.NO_CHANGES;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/main/resources/hudson/plugins/accurev/AccurevSCM/config.jelly:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | AccuRev Configurations
7 |
8 |
10 |
11 |
12 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
61 |
63 |
64 |
65 |
66 |
69 |
70 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/test/java/hudson/plugins/accurev/AccurevSCMTest.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import static jenkins.plugins.accurev.AccurevToolTest.createTool;
4 | import static org.hamcrest.core.Is.is;
5 | import static org.junit.Assert.assertThat;
6 | import static org.mockito.ArgumentMatchers.any;
7 | import static org.mockito.ArgumentMatchers.anyMap;
8 | import static org.mockito.Mockito.doCallRealMethod;
9 | import static org.mockito.Mockito.mock;
10 | import static org.mockito.Mockito.when;
11 |
12 | import com.cloudbees.plugins.credentials.CredentialsProvider;
13 | import com.cloudbees.plugins.credentials.CredentialsStore;
14 | import hudson.model.FreeStyleProject;
15 | import hudson.model.Run;
16 | import hudson.plugins.accurev.AccurevSCM.AccurevSCMDescriptor;
17 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.HashMap;
21 | import java.util.List;
22 | import java.util.Map;
23 | import jenkins.plugins.accurev.AccurevTool;
24 | import org.junit.Before;
25 | import org.junit.Rule;
26 | import org.junit.Test;
27 | import org.jvnet.hudson.test.JenkinsRule;
28 |
29 | public class AccurevSCMTest {
30 |
31 | @Rule public JenkinsRule rule = new JenkinsRule();
32 |
33 | private AccurevSCM scm;
34 | private AccurevServer oldServer;
35 | private FreeStyleProject accurevTest;
36 | private AccurevSCMDescriptor descriptor;
37 | private CredentialsStore store;
38 |
39 | @SuppressWarnings("deprecation")
40 | @Before
41 | public void setUp() throws Exception {
42 | store = CredentialsProvider.lookupStores(rule.jenkins).iterator().next();
43 | oldServer = new AccurevServer(null, "accurevOldServer", "accurevbox.example.org");
44 | oldServer.setUsername("bob");
45 | oldServer.setPassword("OBF:1rwf1x1b1rwf");
46 | descriptor = rule.get(AccurevSCMDescriptor.class);
47 | List servers = new ArrayList<>();
48 | servers.add(oldServer);
49 | descriptor.setServers(servers);
50 | scm = new AccurevSCM("accurevOldServer", "test", "test");
51 | accurevTest = rule.createFreeStyleProject("accurevTest");
52 | accurevTest.setScm(scm);
53 | }
54 |
55 | @SuppressWarnings("deprecation")
56 | @Test
57 | public void shouldSetEnvironmentVariablesWithAccurevSCM() throws IOException {
58 | AccurevSCM scm = mockSCMForBuildEnvVars();
59 |
60 | when(scm.getServer()).thenReturn(oldServer);
61 |
62 | when(scm.getStream()).thenReturn("testStream");
63 |
64 | Run run = mock(Run.class);
65 | Map environment = new HashMap<>();
66 | scm.buildEnvironment(run, environment);
67 |
68 | assertThat(environment.get("ACCUREV_SERVER_HOSTNAME"), is("accurevbox.example.org"));
69 | assertThat(environment.get("ACCUREV_SERVER_PORT"), is("5050"));
70 | assertThat(environment.get("ACCUREV_STREAM"), is("testStream"));
71 | }
72 |
73 | private AccurevSCM mockSCMForBuildEnvVars() {
74 | AccurevSCM scm = mock(AccurevSCM.class);
75 | doCallRealMethod().when(scm).buildEnvironment(any(Run.class), anyMap());
76 | return scm;
77 | }
78 |
79 | @Test
80 | public void testConfigRoundtrip() throws Exception {
81 |
82 | // setup global config - add another server to test that part
83 | List serverList = descriptor.getServers();
84 | serverList.add(new AccurevServer(null, "otherServerName", "otherServerHost"));
85 | descriptor.setServers(serverList);
86 |
87 | accurevTest.setScm(scm);
88 | rule.configRoundtrip(accurevTest);
89 | rule.assertEqualDataBoundBeans(scm, accurevTest.getScm());
90 | }
91 |
92 | @Test
93 | public void testConfigAccurevToolRoundtrip() throws Exception {
94 | AccurevTool.DescriptorImpl tools =
95 | rule.jenkins.getDescriptorByType(AccurevTool.DescriptorImpl.class);
96 | AccurevTool test1 = createTool("test1");
97 | AccurevTool test2 = createTool("test2");
98 | tools.setInstallations(test1, test2);
99 |
100 | scm.setAccurevTool("test2");
101 | accurevTest.setScm(scm);
102 | rule.configRoundtrip(accurevTest);
103 | rule.assertEqualDataBoundBeans(scm, accurevTest.getScm());
104 | }
105 |
106 | @Test
107 | public void testConfigWspaceRoundtrip() throws Exception {
108 |
109 | scm.setWspaceORreftree("wspace");
110 | scm.setWorkspace("testWorkspace1");
111 |
112 | accurevTest.setScm(scm);
113 | rule.configRoundtrip(accurevTest);
114 | rule.assertEqualDataBoundBeans(scm, accurevTest.getScm());
115 | }
116 |
117 | @Test
118 | public void testConfigReftreeRoundtrip() throws Exception {
119 |
120 | scm.setWspaceORreftree("reftree");
121 | scm.setReftree("testRefTree1");
122 |
123 | accurevTest.setScm(scm);
124 | rule.configRoundtrip(accurevTest);
125 | rule.assertEqualDataBoundBeans(scm, accurevTest.getScm());
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/Update.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import hudson.EnvVars;
4 | import hudson.FilePath;
5 | import hudson.Launcher;
6 | import hudson.model.TaskListener;
7 | import hudson.plugins.accurev.AccurevLauncher;
8 | import hudson.plugins.accurev.AccurevSCM;
9 | import hudson.plugins.accurev.XmlParserFactory;
10 | import hudson.plugins.accurev.parsers.output.ParseOutputToFile;
11 | import hudson.plugins.accurev.parsers.xml.ParseUpdate;
12 | import hudson.util.ArgumentListBuilder;
13 | import java.io.File;
14 | import java.io.IOException;
15 | import java.util.ArrayList;
16 | import java.util.Arrays;
17 | import java.util.Collection;
18 | import java.util.List;
19 | import java.util.logging.Logger;
20 | import org.xmlpull.v1.XmlPullParserFactory;
21 |
22 | /** @author raymond */
23 | public class Update extends Command {
24 |
25 | private static final Logger logger = Logger.getLogger(Update.class.getName());
26 | private static final String FFPSCM_DELIM = ",";
27 |
28 | private static ArgumentListBuilder createCommand(
29 | final AccurevSCM.AccurevServer server, //
30 | final boolean preview,
31 | final String reftree,
32 | final boolean minus9) {
33 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
34 | cmd.add("update");
35 | addServer(cmd, server);
36 | cmd.add("-fx");
37 | if (reftree != null) {
38 | cmd.add("-r");
39 | cmd.add(reftree);
40 | }
41 | if (minus9) {
42 | cmd.add("-9");
43 | }
44 |
45 | if (preview) {
46 | cmd.add("-i");
47 | }
48 | return cmd;
49 | }
50 |
51 | public static Boolean hasChanges(
52 | AccurevSCM scm, //
53 | AccurevSCM.AccurevServer server, //
54 | EnvVars accurevEnv, //
55 | FilePath workspace, //
56 | TaskListener listener, //
57 | Launcher launcher, //
58 | String reftree)
59 | throws IOException {
60 |
61 | List files = new ArrayList<>();
62 | final ArgumentListBuilder cmd = createCommand(server, true, reftree, false);
63 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
64 | if (parser == null) {
65 | throw new IOException("No XML Parser");
66 | }
67 | Boolean transactionFound =
68 | AccurevLauncher.runCommand(
69 | "Update command",
70 | scm.getAccurevTool(),
71 | launcher,
72 | cmd,
73 | scm.getOptionalLock(workspace),
74 | accurevEnv,
75 | workspace,
76 | listener,
77 | logger,
78 | parser,
79 | new ParseUpdate(),
80 | files);
81 | if (transactionFound != null && transactionFound) {
82 | String filterForPollSCM = scm.getFilterForPollSCM();
83 | String subPath = scm.getSubPath();
84 | Collection filterPaths = null;
85 | String filterList = null;
86 | if (filterForPollSCM != null && !(filterForPollSCM.isEmpty())) {
87 | filterList = filterForPollSCM;
88 | } else if (subPath != null && !(subPath.isEmpty())) {
89 | filterList = subPath;
90 | }
91 |
92 | if (filterList != null && !filterList.isEmpty()) {
93 | filterList = filterList.replace(", ", ",");
94 | filterPaths = new ArrayList<>(Arrays.asList(filterList.split(FFPSCM_DELIM)));
95 | }
96 |
97 | if (filterPaths != null) {
98 | transactionFound = false;
99 | for (String Filter_For_Poll_SCM1 : filterPaths) {
100 | for (String file : files) {
101 | if (file.contains(Filter_For_Poll_SCM1)) {
102 | transactionFound = true;
103 | break;
104 | }
105 | }
106 | if (transactionFound) {
107 | break;
108 | }
109 | }
110 | }
111 | } else {
112 | return false;
113 | }
114 | return transactionFound;
115 | }
116 |
117 | public static boolean performUpdate(
118 | final AccurevSCM scm, //
119 | final AccurevSCM.AccurevServer server, //
120 | final EnvVars accurevEnv, //
121 | final FilePath workspace, //
122 | final TaskListener listener, //
123 | final Launcher launcher, //
124 | final String reftree,
125 | File changelogFile)
126 | throws IOException {
127 | final ArgumentListBuilder cmd = createCommand(server, false, reftree, false);
128 | final Boolean result =
129 | AccurevLauncher.runCommand(
130 | "Update command",
131 | scm.getAccurevTool(),
132 | launcher,
133 | cmd,
134 | scm.getOptionalLock(workspace),
135 | accurevEnv,
136 | workspace,
137 | listener,
138 | logger,
139 | new ParseOutputToFile(),
140 | changelogFile);
141 | if (result == null) {
142 | return false;
143 | }
144 | return result;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/jenkins/plugins/accurev/AccurevTool.java:
--------------------------------------------------------------------------------
1 | package jenkins.plugins.accurev;
2 |
3 | import static hudson.init.InitMilestone.EXTENSIONS_AUGMENTED;
4 |
5 | import edu.umd.cs.findbugs.annotations.NonNull;
6 | import hudson.EnvVars;
7 | import hudson.Extension;
8 | import hudson.init.Initializer;
9 | import hudson.model.EnvironmentSpecific;
10 | import hudson.model.Node;
11 | import hudson.model.TaskListener;
12 | import hudson.slaves.NodeSpecific;
13 | import hudson.tools.ToolDescriptor;
14 | import hudson.tools.ToolInstallation;
15 | import hudson.tools.ToolProperty;
16 | import hudson.util.FormValidation;
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.util.Collections;
20 | import java.util.List;
21 | import java.util.logging.Logger;
22 | import jenkins.model.Jenkins;
23 | import net.sf.json.JSONObject;
24 | import org.jenkinsci.Symbol;
25 | import org.kohsuke.stapler.DataBoundConstructor;
26 | import org.kohsuke.stapler.QueryParameter;
27 | import org.kohsuke.stapler.StaplerRequest;
28 |
29 | /** Initialized by josep on 21-01-2017. */
30 | public class AccurevTool extends ToolInstallation
31 | implements NodeSpecific, EnvironmentSpecific {
32 |
33 | private static final String DEFAULT = "Default";
34 | private static final long serialVersionUID = 1;
35 | private static final Logger LOGGER = Logger.getLogger(AccurevTool.class.getName());
36 |
37 | /**
38 | * Constructor for AccurevTool
39 | *
40 | * @param name Tool name
41 | * @param home Tool location (usually "accurev")
42 | * @param properties {@link java.util.List} of properties for this tool
43 | */
44 | @DataBoundConstructor
45 | public AccurevTool(String name, String home, List extends ToolProperty>> properties) {
46 | super(name, home, properties);
47 | }
48 |
49 | private static AccurevTool[] getInstallations(DescriptorImpl descriptor) {
50 |
51 | if (descriptor == null) {
52 | return new AccurevTool[0];
53 | } else {
54 | return descriptor.getInstallations();
55 | }
56 | }
57 |
58 | /**
59 | * Returns the default installation.
60 | *
61 | * @return default installation
62 | */
63 | public static AccurevTool getDefaultInstallation() {
64 | Jenkins jenkinsInstance = Jenkins.get();
65 | DescriptorImpl AccurevTools =
66 | jenkinsInstance.getDescriptorByType(AccurevTool.DescriptorImpl.class);
67 | AccurevTool tool = AccurevTools.getInstallation(AccurevTool.DEFAULT);
68 | if (tool != null) {
69 | return tool;
70 | } else {
71 | AccurevTool[] installations = AccurevTools.getInstallations();
72 | if (installations.length > 0) {
73 | return installations[0];
74 | } else {
75 | onLoaded();
76 | return AccurevTools.getInstallations()[0];
77 | }
78 | }
79 | }
80 |
81 | @Initializer(after = EXTENSIONS_AUGMENTED)
82 | public static void onLoaded() {
83 | // Creates default tool installation if needed. Uses "accurev" or migrates data from previous
84 | // versions
85 |
86 | Jenkins jenkinsInstance = Jenkins.get();
87 |
88 | DescriptorImpl descriptor = (DescriptorImpl) jenkinsInstance.getDescriptor(AccurevTool.class);
89 | AccurevTool[] installations = getInstallations(descriptor);
90 |
91 | if (installations != null && installations.length > 0) {
92 | // No need to initialize if there's already something
93 | return;
94 | }
95 |
96 | String defaultAccurevExe = "accurev";
97 | AccurevTool tool = new AccurevTool(DEFAULT, defaultAccurevExe, Collections.emptyList());
98 | if (descriptor != null) {
99 | descriptor.setInstallations(tool);
100 | descriptor.save();
101 | }
102 | }
103 |
104 | public AccurevTool forNode(@NonNull Node node, TaskListener log)
105 | throws IOException, InterruptedException {
106 | return new AccurevTool(getName(), translateFor(node, log), Collections.emptyList());
107 | }
108 |
109 | public AccurevTool forEnvironment(EnvVars environment) {
110 | return new AccurevTool(getName(), environment.expand(getHome()), Collections.emptyList());
111 | }
112 |
113 | @Override
114 | public DescriptorImpl getDescriptor() {
115 | Jenkins jenkinsInstance = Jenkins.get();
116 | return (DescriptorImpl) jenkinsInstance.getDescriptorOrDie(getClass());
117 | }
118 |
119 | @Extension
120 | @Symbol("accurevTool")
121 | public static final class DescriptorImpl extends ToolDescriptor {
122 |
123 | public DescriptorImpl() {
124 | super();
125 | load();
126 | }
127 |
128 | @Override
129 | @NonNull
130 | public String getDisplayName() {
131 | return "AccuRev";
132 | }
133 |
134 | @SuppressWarnings("SuspiciousToArrayCall")
135 | @Override
136 | public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
137 | setInstallations(req.bindJSONToList(clazz, json.get("tool")).toArray(new AccurevTool[0]));
138 | save();
139 | return true;
140 | }
141 |
142 | public FormValidation doCheckHome(@QueryParameter File value) {
143 | Jenkins.get().checkPermission(Jenkins.ADMINISTER);
144 | String path = value.getPath();
145 |
146 | return FormValidation.validateExecutable(path);
147 | }
148 |
149 | public AccurevTool getInstallation(String name) {
150 | for (AccurevTool i : getInstallations()) {
151 | if (i.getName().equals(name)) {
152 | return i;
153 | }
154 | }
155 | return null;
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/AccurevStream.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import java.io.IOException;
4 | import java.io.ObjectInputStream;
5 | import java.io.Serializable;
6 | import java.util.Date;
7 | import java.util.HashSet;
8 | import java.util.Set;
9 |
10 | /**
11 | * Created by IntelliJ IDEA.
12 | *
13 | * @author connollys
14 | * @since 03-Dec-2007 10:58:32
15 | */
16 | public class AccurevStream implements Serializable {
17 |
18 | private static final long serialVersionUID = 8004696899509026973L;
19 | private final String name;
20 | private final Long number;
21 | private final String depot;
22 | private final String basisName;
23 | private final Long basisNumber;
24 | private final boolean dynamic;
25 | private final StreamType type;
26 | private final Date time;
27 | private final Date startTime;
28 | private transient AccurevStream parent;
29 | private transient Set children = new HashSet<>();
30 |
31 | public AccurevStream(
32 | String name,
33 | Long number,
34 | String depot,
35 | String basisName,
36 | Long basisNumber,
37 | boolean dynamic,
38 | StreamType type,
39 | Date time,
40 | Date startTime) {
41 | this.name = name;
42 | this.number = number;
43 | this.depot = depot;
44 | this.basisName = basisName;
45 | this.basisNumber = basisNumber;
46 | this.dynamic = dynamic;
47 | this.type = type;
48 | this.time = time == null ? null : (Date) time.clone();
49 | this.startTime = startTime == null ? null : (Date) startTime.clone();
50 | }
51 |
52 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
53 | in.defaultReadObject();
54 |
55 | children = new HashSet<>();
56 | }
57 |
58 | /**
59 | * Getter for property 'name'.
60 | *
61 | * @return Value for property 'name'.
62 | */
63 | public String getName() {
64 | return name;
65 | }
66 |
67 | /**
68 | * Getter for property 'number'.
69 | *
70 | * @return Value for property 'number'.
71 | */
72 | public Long getNumber() {
73 | return number;
74 | }
75 |
76 | /**
77 | * Getter for property 'depot'.
78 | *
79 | * @return Value for property 'depot'.
80 | */
81 | public String getDepot() {
82 | return depot;
83 | }
84 |
85 | /**
86 | * Getter for property 'basisName'.
87 | *
88 | * @return Value for property 'basisName'.
89 | */
90 | public String getBasisName() {
91 | return basisName;
92 | }
93 |
94 | /**
95 | * Getter for property 'basisNumber'.
96 | *
97 | * @return Value for property 'basisNumber'.
98 | */
99 | public Long getBasisNumber() {
100 | return basisNumber;
101 | }
102 |
103 | /**
104 | * Getter for property 'dynamic'.
105 | *
106 | * @return Value for property 'dynamic'.
107 | */
108 | public boolean isDynamic() {
109 | return dynamic;
110 | }
111 |
112 | /**
113 | * Getter for property 'type'.
114 | *
115 | * @return Value for property 'type'.
116 | */
117 | public StreamType getType() {
118 | return type;
119 | }
120 |
121 | /**
122 | * Getter for property 'time'.
123 | *
124 | * @return Value for property 'time'.
125 | */
126 | public Date getTime() {
127 | return (Date) time.clone();
128 | }
129 |
130 | /**
131 | * Getter for property 'startTime'.
132 | *
133 | * @return Value for property 'startTime'.
134 | */
135 | public Date getStartTime() {
136 | return (Date) startTime.clone();
137 | }
138 |
139 | /**
140 | * Getter for property 'parent'.
141 | *
142 | * @return Value for property 'parent'.
143 | */
144 | public AccurevStream getParent() {
145 | return parent;
146 | }
147 |
148 | /**
149 | * Setter for property 'parent'.
150 | *
151 | * @param parent Value to set for property 'parent'.
152 | */
153 | public void setParent(AccurevStream parent) {
154 | if (this.parent != parent) {
155 | if (this.parent != null) {
156 | this.parent.getChildren().remove(this);
157 | }
158 | this.parent = parent;
159 | if (this.parent != null) {
160 | this.parent.getChildren().add(this);
161 | }
162 | }
163 | }
164 |
165 | /**
166 | * Getter for property 'children'.
167 | *
168 | * @return Value for property 'children'.
169 | */
170 | public Set getChildren() {
171 | return children;
172 | }
173 |
174 | /**
175 | * Returns true if and only if the stream propagates changes from it's parent.
176 | *
177 | * @return true if and only if the stream propagates changes from it's parent.
178 | */
179 | public boolean isReceivingChangesFromParent() {
180 | switch (type) {
181 | case WORKSPACE:
182 | return true;
183 | case PASSTHROUGH:
184 | return true;
185 | case SNAPSHOT:
186 | return false;
187 | case GATED:
188 | return true;
189 | case STAGING:
190 | return true;
191 | case NORMAL:
192 | // TODO need to add an optimization, namely check to see if a time is present, has it
193 | // changed
194 | // since last we checked.
195 | return time == null;
196 | default:
197 | return false;
198 | }
199 | }
200 |
201 | public enum StreamType {
202 | NORMAL("normal"),
203 | SNAPSHOT("snapshot"),
204 | WORKSPACE("workspace"),
205 | PASSTHROUGH("passthrough"),
206 | GATED("gated"),
207 | STAGING("staging"),
208 | ;
209 | private final String type;
210 |
211 | StreamType(String type) {
212 | this.type = type;
213 | }
214 |
215 | public static StreamType parseStreamType(String streamType) {
216 | for (StreamType value : values()) {
217 | if (value.type.equalsIgnoreCase(streamType)) {
218 | return value;
219 | }
220 | }
221 | throw new NumberFormatException("Unknown stream type: " + streamType);
222 | }
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/ShowStreams.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import edu.umd.cs.findbugs.annotations.CheckForNull;
4 | import hudson.EnvVars;
5 | import hudson.FilePath;
6 | import hudson.Launcher;
7 | import hudson.model.TaskListener;
8 | import hudson.plugins.accurev.AccurevLauncher;
9 | import hudson.plugins.accurev.AccurevSCM;
10 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
11 | import hudson.plugins.accurev.AccurevStream;
12 | import hudson.plugins.accurev.XmlParserFactory;
13 | import hudson.plugins.accurev.parsers.xml.ParseShowStreams;
14 | import hudson.util.ArgumentListBuilder;
15 | import java.io.IOException;
16 | import java.util.HashMap;
17 | import java.util.Map;
18 | import java.util.concurrent.locks.ReentrantLock;
19 | import java.util.logging.Logger;
20 | import org.xmlpull.v1.XmlPullParserFactory;
21 |
22 | public class ShowStreams extends Command {
23 |
24 | private static final Logger LOGGER = Logger.getLogger(ShowStreams.class.getName());
25 |
26 | @CheckForNull
27 | public static Map getStreams( //
28 | final AccurevSCM scm, //
29 | final String nameOfStreamRequired, //
30 | final AccurevServer server, //
31 | final EnvVars accurevEnv, //
32 | final FilePath workspace, //
33 | final TaskListener listener, //
34 | final Launcher launcher)
35 | throws IOException {
36 | final Map streams;
37 | if (scm.isIgnoreStreamParent()) {
38 | streams = getOneStream(nameOfStreamRequired, accurevEnv, workspace, listener, launcher, scm);
39 | } else if (server.isUseRestrictedShowStreams()) {
40 | streams =
41 | getAllAncestorStreams(
42 | nameOfStreamRequired, scm, accurevEnv, workspace, listener, launcher);
43 | } else {
44 | streams =
45 | getAllStreams(
46 | scm,
47 | server,
48 | scm.getDepot(),
49 | scm.getOptionalLock(workspace),
50 | accurevEnv,
51 | workspace,
52 | listener,
53 | launcher);
54 | }
55 | return streams;
56 | }
57 |
58 | public static Map getAllStreams( //
59 | AccurevSCM scm,
60 | final AccurevServer server, //
61 | final String depot, //
62 | final ReentrantLock lock, //
63 | final EnvVars accurevEnv, //
64 | final FilePath workspace, //
65 | final TaskListener listener, //
66 | final Launcher launcher)
67 | throws IOException {
68 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
69 | cmd.add("show");
70 | addServer(cmd, server);
71 | cmd.add("-fx");
72 | cmd.add("-p");
73 | cmd.add(depot);
74 | cmd.add("streams");
75 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
76 | if (parser == null) {
77 | throw new IOException("No XML Parser");
78 | }
79 | final Map streams =
80 | AccurevLauncher.runCommand(
81 | "Show streams command",
82 | scm.getAccurevTool(),
83 | launcher,
84 | cmd,
85 | lock,
86 | accurevEnv,
87 | workspace,
88 | listener,
89 | LOGGER,
90 | parser,
91 | new ParseShowStreams(),
92 | depot);
93 | setParents(streams);
94 | return streams;
95 | }
96 |
97 | private static Map getAllAncestorStreams( //
98 | final String nameOfStreamRequired, //
99 | final AccurevSCM scm,
100 | final EnvVars accurevEnv, //
101 | final FilePath workspace, //
102 | final TaskListener listener, //
103 | final Launcher launcher)
104 | throws IOException {
105 | final Map streams = new HashMap<>();
106 | String streamName = nameOfStreamRequired;
107 | while (streamName != null && !streamName.isEmpty()) {
108 | final Map oneStream =
109 | getOneStream(streamName, accurevEnv, workspace, listener, launcher, scm);
110 | final AccurevStream theStream = oneStream == null ? null : oneStream.get(streamName);
111 | streamName = null;
112 | if (theStream != null) {
113 | if (theStream.getBasisName() != null) {
114 | streamName = theStream.getBasisName();
115 | } else if (theStream.getBasisNumber() != null) {
116 | streamName = theStream.getBasisNumber().toString();
117 | }
118 | streams.putAll(oneStream);
119 | }
120 | }
121 | setParents(streams);
122 | return streams;
123 | }
124 |
125 | private static Map getOneStream( //
126 | final String streamName, //
127 | final EnvVars accurevEnv, //
128 | final FilePath workspace, //
129 | final TaskListener listener, //
130 | final Launcher launcher,
131 | AccurevSCM scm)
132 | throws IOException {
133 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
134 | cmd.add("show");
135 | addServer(cmd, scm.getServer());
136 | cmd.add("-fx");
137 | cmd.add("-p");
138 | cmd.add(scm.getDepot());
139 | cmd.add("-s");
140 | cmd.add(streamName);
141 | cmd.add("streams");
142 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
143 | if (parser == null) {
144 | throw new IOException("No XML Parser");
145 | }
146 | return AccurevLauncher.runCommand(
147 | "Restricted show streams command",
148 | scm.getAccurevTool(),
149 | launcher,
150 | cmd,
151 | scm.getOptionalLock(workspace),
152 | accurevEnv,
153 | workspace,
154 | listener,
155 | LOGGER,
156 | parser,
157 | new ParseShowStreams(),
158 | scm.getDepot());
159 | }
160 |
161 | private static void setParents(Map streams) {
162 | // build the tree
163 | if (streams != null && streams.size() > 1) {
164 | streams
165 | .values()
166 | .stream()
167 | .filter(stream -> stream.getBasisName() != null)
168 | .forEach(stream -> stream.setParent(streams.get(stream.getBasisName())));
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/Login.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
4 | import hudson.EnvVars;
5 | import hudson.FilePath;
6 | import hudson.Launcher;
7 | import hudson.model.TaskListener;
8 | import hudson.plugins.accurev.AccurevLauncher;
9 | import hudson.plugins.accurev.AccurevSCM;
10 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
11 | import hudson.plugins.accurev.parsers.output.ParseInfoToLoginName;
12 | import hudson.util.ArgumentListBuilder;
13 | import hudson.util.Secret;
14 | import java.io.IOException;
15 | import java.util.concurrent.locks.ReentrantLock;
16 | import java.util.logging.Logger;
17 | import jenkins.model.Jenkins;
18 | import org.apache.commons.lang.StringUtils;
19 |
20 | public class Login extends Command {
21 |
22 | private static final Logger logger = Logger.getLogger(Login.class.getName());
23 |
24 | /**
25 | * @return The currently logged in user "Principal" name, which may be "(not logged in)" if not
26 | * logged in.
27 | * Returns null on failure.
28 | */
29 | private static String getLoggedInUsername( //
30 | String accurevTool,
31 | final AccurevServer server, //
32 | final EnvVars accurevEnv, //
33 | final FilePath workspace, //
34 | final TaskListener listener, //
35 | final Launcher launcher)
36 | throws IOException {
37 | final String commandDescription = "info command";
38 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
39 | cmd.add("info");
40 | addServer(cmd, server);
41 | // returns username
42 | return AccurevLauncher.runCommand(
43 | commandDescription,
44 | accurevTool,
45 | launcher,
46 | cmd,
47 | null,
48 | accurevEnv,
49 | workspace,
50 | listener,
51 | logger,
52 | new ParseInfoToLoginName(),
53 | null);
54 | }
55 |
56 | public static boolean ensureLoggedInToAccurev(
57 | AccurevSCM scm,
58 | AccurevServer server,
59 | EnvVars accurevEnv,
60 | FilePath pathToRunCommandsIn,
61 | TaskListener listener,
62 | Launcher launcher)
63 | throws IOException {
64 | String accurevTool = scm == null ? null : scm.getAccurevTool();
65 | if (server == null) {
66 | listener.getLogger().println("Authentication failure - Server is empty");
67 | return false;
68 | }
69 | final String requiredUsername = server.getUsername();
70 | if (StringUtils.isBlank(requiredUsername)) {
71 | listener.getLogger().println("Authentication failure - Username blank");
72 | return false;
73 | }
74 | ReentrantLock lock =
75 | (scm == null) ? AccurevSCM.MASTER_LOCK : scm.getMandatoryLock(pathToRunCommandsIn);
76 | lock.lock();
77 |
78 | try {
79 | final boolean loginRequired;
80 | if (server.isMinimiseLogins()) {
81 | final String currentUsername =
82 | getLoggedInUsername(
83 | accurevTool, server, accurevEnv, pathToRunCommandsIn, listener, launcher);
84 | if (StringUtils.isEmpty(currentUsername)) {
85 | loginRequired = true;
86 | listener.getLogger().println("Not currently authenticated with AccuRev server");
87 | } else {
88 | loginRequired = !currentUsername.equals(requiredUsername);
89 | listener
90 | .getLogger()
91 | .println(
92 | "Currently authenticated with AccuRev server as '"
93 | + currentUsername
94 | + (loginRequired ? "', login required" : "', not logging in again."));
95 | }
96 | } else {
97 | loginRequired = true;
98 | }
99 | if (loginRequired) {
100 | return accurevLogin(
101 | accurevTool, server, accurevEnv, pathToRunCommandsIn, listener, launcher);
102 | }
103 | } finally {
104 | lock.unlock();
105 | }
106 | return true;
107 | }
108 |
109 | private static boolean accurevLogin(
110 | String accurevTool,
111 | final AccurevServer server, //
112 | final EnvVars accurevEnv, //
113 | final FilePath workspace, //
114 | final TaskListener listener, //
115 | final Launcher launcher)
116 | throws IOException {
117 | StandardUsernamePasswordCredentials credentials = server.getCredentials();
118 | if (credentials == null) {
119 | listener.getLogger().println("Credentials not found");
120 | return false;
121 | }
122 | if (StringUtils.isBlank(credentials.getUsername())) {
123 | listener.getLogger().println("Credentials username cannot be blank");
124 | return false;
125 | }
126 | listener.getLogger().println("Authenticating with AccuRev server...");
127 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
128 | cmd.add("login");
129 | addServer(cmd, server);
130 | if (server.isUseNonexpiringLogin()) {
131 | cmd.add("-n");
132 | }
133 | cmd.add(credentials.getUsername());
134 | if (StringUtils.isEmpty(Secret.toString(credentials.getPassword()))) {
135 | if (launcher.isUnix()) {
136 | cmd.add("", true);
137 | } else {
138 | cmd.addQuoted("", true);
139 | }
140 | } else {
141 | cmd.add(server.getPassword(), true);
142 | }
143 | final boolean success =
144 | AccurevLauncher.runCommand(
145 | "login", accurevTool, launcher, cmd, null, accurevEnv, workspace, listener, logger);
146 | if (success) {
147 | listener.getLogger().println("Authentication completed successfully.");
148 | return true;
149 | } else {
150 | return false;
151 | }
152 | }
153 |
154 | /**
155 | * @param server Accurev Server
156 | * @return boolean whether am successful
157 | * @throws IOException failing IO This method is called from doFillStreams and doFillDepots while
158 | * configuring the job
159 | */
160 | public static boolean accurevLoginFromGlobalConfig( //
161 | final AccurevServer server) throws IOException {
162 |
163 | Jenkins jenkins = Jenkins.get();
164 | TaskListener listener = TaskListener.NULL;
165 | Launcher launcher = jenkins.createLauncher(listener);
166 | EnvVars accurevEnv = new EnvVars();
167 |
168 | return ensureLoggedInToAccurev(
169 | null, server, accurevEnv, jenkins.getRootPath(), listener, launcher);
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/AccurevTransaction.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4 | import hudson.model.User;
5 | import hudson.scm.ChangeLogSet;
6 | import hudson.scm.EditType;
7 | import java.util.ArrayList;
8 | import java.util.Collection;
9 | import java.util.Date;
10 | import java.util.List;
11 | import org.apache.commons.lang.StringUtils;
12 | import org.kohsuke.stapler.export.Exported;
13 | import org.kohsuke.stapler.export.ExportedBean;
14 |
15 | /** One commit. */
16 | @ExportedBean(defaultVisibility = 999)
17 | public final class AccurevTransaction extends ChangeLogSet.Entry {
18 |
19 | private static final String FIELD_SEPARATOR = ", ";
20 | private static final String EQ = "=";
21 | private final List affectedPaths = new ArrayList<>();
22 | private final List affectedRawPaths = new ArrayList<>();
23 | private final List fileRevisions = new ArrayList<>();
24 | // private String revision;
25 | private User author;
26 | private Date date;
27 | private String msg;
28 | private String action;
29 | private String id;
30 | private String issueNum;
31 | private String webuiURLforTrans;
32 | private String webuiURLforIssue;
33 |
34 | @Exported
35 | public String getIssueNum() {
36 | return issueNum;
37 | }
38 |
39 | public void setIssueNum(String issueNum) {
40 | this.issueNum = issueNum;
41 | }
42 |
43 | @Exported
44 | public String getWebuiURLforTrans() {
45 | return webuiURLforTrans;
46 | }
47 |
48 | public void setWebuiURLforTrans(String webuiURLforTrans) {
49 | this.webuiURLforTrans = webuiURLforTrans;
50 | }
51 |
52 | /*@Exported
53 | public String getRevision() {
54 | return revision;
55 | }*/
56 |
57 | @Exported
58 | public String getWebuiURLforIssue() {
59 | return webuiURLforIssue;
60 | }
61 |
62 | public void setWebuiURLforIssue(String webuiURLforIssue) {
63 | this.webuiURLforIssue = webuiURLforIssue;
64 | }
65 |
66 | public void addFileRevision(String revision) {
67 | fileRevisions.add(revision);
68 | }
69 |
70 | @Exported
71 | public User getAuthor() {
72 | return author;
73 | }
74 |
75 | /**
76 | * Returns a set of paths in the workspace that was affected by this change. Contains string like
77 | * 'foo/bar/zot'. No leading/trailing '/', and separator must be normalized to '/'.
78 | *
79 | * @return never null.
80 | */
81 | @Exported
82 | public Collection getAffectedPaths() {
83 | return affectedPaths;
84 | }
85 |
86 | public List getAffectedRawPaths() {
87 | return affectedRawPaths;
88 | }
89 |
90 | @Exported
91 | public Collection getFileRevisions() {
92 | return fileRevisions;
93 | }
94 |
95 | @Exported
96 | @SuppressFBWarnings(
97 | value = "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR",
98 | justification = "We hope that AccurevTransaction.author is not null here... Need to fix.")
99 | public String getUser() { // digester wants read/write property, even though it never reads. Duh.
100 | return author.getDisplayName();
101 | }
102 |
103 | public void setUser(String author) {
104 | this.author = User.getById(author, true);
105 | }
106 |
107 | @Exported
108 | @SuppressFBWarnings(
109 | value = "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR",
110 | justification = "We hope that AccurevTransaction.date is not null here... Need to fix.")
111 | public Date getDate() {
112 | return (Date) date.clone();
113 | }
114 |
115 | public void setDate(Date date) {
116 | this.date = (Date) date.clone();
117 | }
118 |
119 | @Exported
120 | public String getMsg() {
121 | return (StringUtils.isEmpty(msg) ? "" : msg);
122 | }
123 |
124 | public void setMsg(String msg) {
125 | this.msg = msg;
126 | }
127 |
128 | protected void setParent(ChangeLogSet parent) {
129 | super.setParent(parent); // Needed since parent method is protected
130 | }
131 |
132 | @Exported
133 | @SuppressFBWarnings(
134 | value = "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR",
135 | justification = "We hope that AccurevTransaction.action is not null here... Need to fix.")
136 | public EditType getEditType() {
137 | if (action.equals("promote")) {
138 | return EditType.EDIT;
139 | }
140 | if (action.equals("defunct")) {
141 | return EditType.DELETE;
142 | }
143 | if (action.equals("chstream")) {
144 | return EditType.EDIT;
145 | }
146 | if (action.equals("add")) {
147 | return EditType.ADD;
148 | }
149 | return EditType.EDIT;
150 | }
151 |
152 | public void addAffectedPath(String path) {
153 | affectedPaths.add(path);
154 | }
155 |
156 | public void addAffectedRawPath(String path) {
157 | affectedRawPaths.add(path);
158 | }
159 |
160 | /**
161 | * Getter for action Enables accurate filtering by AccuRev transaction type since the metod
162 | * getEditType censors the actual type.
163 | *
164 | * @return transaction type of the AccuRev transaction
165 | */
166 | @Exported
167 | public String getAction() {
168 | return action;
169 | }
170 |
171 | public void setAction(String action) {
172 | this.action = action;
173 | if ("chstream".equals(action) && StringUtils.isEmpty(msg)) {
174 | msg = "Changed Parent Stream";
175 | }
176 | }
177 |
178 | /**
179 | * Getter for id Enables logging with AccuRev transaction id
180 | *
181 | * @return transaction id of the AccuRev transaction
182 | */
183 | @Exported
184 | public String getId() {
185 | return id;
186 | }
187 |
188 | /**
189 | * Setter for id
190 | *
191 | * @param id transaction id of the AccuRev transaction
192 | */
193 | public void setId(String id) {
194 | this.id = id;
195 | }
196 |
197 | @Override
198 | public String toString() {
199 | return '['
200 | + //
201 | "id"
202 | + EQ
203 | + id
204 | + //
205 | FIELD_SEPARATOR
206 | + //
207 | "date"
208 | + EQ
209 | + date
210 | + //
211 | FIELD_SEPARATOR
212 | + //
213 | "author"
214 | + EQ
215 | + author
216 | + //
217 | FIELD_SEPARATOR
218 | + //
219 | "action"
220 | + EQ
221 | + action
222 | + //
223 | FIELD_SEPARATOR
224 | + //
225 | "msg"
226 | + EQ
227 | + getMsg()
228 | + //
229 | ']';
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/ChangeLogCmd.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import hudson.EnvVars;
4 | import hudson.FilePath;
5 | import hudson.Launcher;
6 | import hudson.model.TaskListener;
7 | import hudson.plugins.accurev.AccurevLauncher;
8 | import hudson.plugins.accurev.AccurevSCM;
9 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
10 | import hudson.plugins.accurev.GetConfigWebURL;
11 | import hudson.plugins.accurev.XmlParserFactory;
12 | import hudson.plugins.accurev.parsers.output.ParseOutputToFile;
13 | import hudson.plugins.accurev.parsers.xml.ParseGetConfig;
14 | import hudson.util.ArgumentListBuilder;
15 | import java.io.File;
16 | import java.io.IOException;
17 | import java.text.SimpleDateFormat;
18 | import java.util.Date;
19 | import java.util.Map;
20 | import java.util.logging.Logger;
21 | import javax.xml.parsers.DocumentBuilder;
22 | import javax.xml.parsers.DocumentBuilderFactory;
23 | import javax.xml.parsers.ParserConfigurationException;
24 | import javax.xml.transform.Transformer;
25 | import javax.xml.transform.TransformerException;
26 | import javax.xml.transform.TransformerFactory;
27 | import javax.xml.transform.dom.DOMSource;
28 | import javax.xml.transform.stream.StreamResult;
29 | import org.w3c.dom.Document;
30 | import org.w3c.dom.Element;
31 | import org.w3c.dom.NodeList;
32 | import org.xml.sax.SAXException;
33 | import org.xmlpull.v1.XmlPullParserFactory;
34 |
35 | public class ChangeLogCmd {
36 |
37 | public static boolean captureChangelog(
38 | AccurevServer server,
39 | EnvVars accurevEnv,
40 | FilePath workspace,
41 | TaskListener listener,
42 | Launcher launcher,
43 | Date buildDate,
44 | Date startDate,
45 | String stream,
46 | File changelogFile,
47 | Logger logger,
48 | AccurevSCM scm,
49 | Map webURL)
50 | throws IOException {
51 | final String accurevACSYNCEnvVar = "AC_SYNC";
52 | if (!accurevEnv.containsKey(accurevACSYNCEnvVar)) {
53 | final String accurevACSYNC = "IGNORE";
54 | accurevEnv.put(accurevACSYNCEnvVar, accurevACSYNC);
55 | listener
56 | .getLogger()
57 | .println("Setting " + accurevACSYNCEnvVar + " to \"" + accurevACSYNC + '"');
58 | }
59 | ArgumentListBuilder cmd = new ArgumentListBuilder();
60 | cmd.add("hist");
61 | Command.addServer(cmd, server);
62 | cmd.add("-fx");
63 | cmd.add("-a");
64 | cmd.add("-s");
65 | cmd.add(stream);
66 | cmd.add("-t");
67 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
68 | String dateRange = formatter.format(buildDate);
69 | if (startDate != null) {
70 | dateRange += "-" + formatter.format(startDate);
71 | } else {
72 | dateRange += ".100";
73 | }
74 | cmd.add(dateRange); // if this breaks windows there's going to be fun
75 | final String commandDescription = "Changelog command";
76 | final Boolean success =
77 | AccurevLauncher.runCommand(
78 | commandDescription,
79 | scm.getAccurevTool(),
80 | launcher,
81 | cmd,
82 | scm.getOptionalLock(workspace),
83 | accurevEnv,
84 | workspace,
85 | listener,
86 | logger,
87 | new ParseOutputToFile(),
88 | changelogFile);
89 | if (success == null || !success) {
90 | return false;
91 | }
92 | // ==============================================================================================
93 | // See the content of changelogfile
94 |
95 | if (changelogFile != null) {
96 | applyWebURL(webURL, changelogFile, scm);
97 | }
98 | // =============================================================================================
99 | listener.getLogger().println("Changelog calculated successfully.");
100 | return true;
101 | }
102 |
103 | /**
104 | * Retrieve the settings.xml file to get the webURL.
105 | *
106 | * @param server Server
107 | * @param accurevEnv Accurev Environment
108 | * @param workspace Workspace
109 | * @param listener listener
110 | * @param launcher Launcher
111 | * @param logger logger
112 | * @param scm Accurev SCM
113 | * @return webURL
114 | * @throws IOException Handle it above
115 | */
116 | public static Map retrieveWebURL(
117 | AccurevServer server,
118 | EnvVars accurevEnv,
119 | FilePath workspace,
120 | TaskListener listener,
121 | Launcher launcher,
122 | Logger logger,
123 | AccurevSCM scm)
124 | throws IOException {
125 | final ArgumentListBuilder getConfigCmd = new ArgumentListBuilder();
126 | getConfigCmd.add("getconfig");
127 | Command.addServer(getConfigCmd, server);
128 | getConfigCmd.add("-s");
129 | getConfigCmd.add("-r");
130 | getConfigCmd.add("settings.xml");
131 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
132 | if (parser == null) {
133 | throw new IOException("No XML Parser");
134 | }
135 |
136 | return AccurevLauncher.runCommand(
137 | "Get config to fetch webURL",
138 | scm.getAccurevTool(),
139 | launcher,
140 | getConfigCmd,
141 | scm.getOptionalLock(workspace),
142 | accurevEnv,
143 | workspace,
144 | listener,
145 | logger,
146 | parser,
147 | new ParseGetConfig(),
148 | null);
149 | }
150 |
151 | /**
152 | * Parses changelog to apply the given webURL
153 | *
154 | * @param webURL webURL
155 | * @param changelogFile changeLogFile
156 | * @param scm Accurev SCM
157 | */
158 | private static void applyWebURL(
159 | Map webURL, File changelogFile, AccurevSCM scm) {
160 |
161 | if (webURL == null || webURL.isEmpty()) {
162 | return;
163 | }
164 |
165 | GetConfigWebURL webuiURL = webURL.get("webuiURL");
166 | DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
167 | DocumentBuilder documentBuilder;
168 | try {
169 | documentBuilder = documentBuilderFactory.newDocumentBuilder();
170 | Document document = documentBuilder.parse(changelogFile);
171 |
172 | NodeList nodes = document.getElementsByTagName("transaction");
173 |
174 | Element depotElement = document.createElement("depot");
175 | if (nodes != null && nodes.getLength() > 0) {
176 | nodes.item(0).getParentNode().insertBefore(depotElement, nodes.item(0));
177 | }
178 |
179 | depotElement.appendChild(document.createTextNode(scm.getDepot()));
180 |
181 | Element webuiElement = document.createElement("webuiURL");
182 | if (nodes != null && nodes.getLength() > 0) {
183 | nodes.item(0).getParentNode().insertBefore(webuiElement, nodes.item(0));
184 | }
185 |
186 | if (webuiURL != null) {
187 | webuiElement.appendChild(
188 | document.createTextNode(
189 | (webuiURL.getWebURL().endsWith("/")
190 | ? (webuiURL.getWebURL().substring(0, webuiURL.getWebURL().length() - 1))
191 | : (webuiURL.getWebURL()))));
192 | } else {
193 | webuiElement.appendChild(document.createTextNode(""));
194 | }
195 |
196 | DOMSource source = new DOMSource(document);
197 |
198 | TransformerFactory transformerFactory = TransformerFactory.newInstance();
199 | Transformer transformer = transformerFactory.newTransformer();
200 | StreamResult result = new StreamResult(changelogFile);
201 | transformer.transform(source, result);
202 | } catch (ParserConfigurationException
203 | | IOException
204 | | SAXException
205 | | TransformerException ignored) {
206 |
207 | }
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/cmd/History.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.cmd;
2 |
3 | import hudson.EnvVars;
4 | import hudson.FilePath;
5 | import hudson.Launcher;
6 | import hudson.model.TaskListener;
7 | import hudson.plugins.accurev.AccurevLauncher;
8 | import hudson.plugins.accurev.AccurevSCM;
9 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
10 | import hudson.plugins.accurev.AccurevTransaction;
11 | import hudson.plugins.accurev.XmlParserFactory;
12 | import hudson.plugins.accurev.parsers.xml.ParseHistory;
13 | import hudson.util.ArgumentListBuilder;
14 | import java.io.IOException;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 | import java.util.logging.Logger;
18 | import org.xmlpull.v1.XmlPullParserFactory;
19 |
20 | public class History extends Command {
21 |
22 | private static final Logger logger = Logger.getLogger(History.class.getName());
23 |
24 | /**
25 | * @param scm Accurev SCM
26 | * @param server server
27 | * @param accurevEnv Accurev Enviroment
28 | * @param workspace workspace
29 | * @param listener listener
30 | * @param launcher launcher
31 | * @param stream stream
32 | * @param transactionType Transaction type Specify what type of transaction to search for (can be
33 | * null)
34 | * @return the latest transaction of the specified type from the selected stream
35 | * @throws IOException if no transaction was found
36 | */
37 | public static AccurevTransaction getLatestTransaction( //
38 | final AccurevSCM scm, //
39 | final AccurevServer server, //
40 | final EnvVars accurevEnv, //
41 | final FilePath workspace, //
42 | final TaskListener listener, //
43 | final Launcher launcher, //
44 | final String stream, //
45 | final String transactionType)
46 | throws IOException {
47 | // initialize code that extracts the latest transaction of a certain
48 | // type using -k flag
49 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
50 | cmd.add("hist");
51 | addServer(cmd, server);
52 | cmd.add("-fx");
53 | cmd.add("-p");
54 | cmd.add(scm.getDepot());
55 | cmd.add("-s");
56 | cmd.add(stream);
57 | cmd.add("-t");
58 | cmd.add("now.1");
59 | if (transactionType != null) {
60 | cmd.add("-k");
61 | cmd.add(transactionType);
62 | }
63 |
64 | // execute code that extracts the latest transaction
65 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
66 | if (parser == null) {
67 | throw new IOException("No XML Parser");
68 | }
69 | final List transaction = new ArrayList<>(1);
70 | final Boolean transactionFound =
71 | AccurevLauncher.runCommand(
72 | "History command",
73 | scm.getAccurevTool(),
74 | launcher,
75 | cmd,
76 | scm.getOptionalLock(workspace),
77 | accurevEnv,
78 | workspace,
79 | listener,
80 | logger,
81 | parser,
82 | new ParseHistory(),
83 | transaction);
84 | if (transactionFound == null) {
85 | final String msg =
86 | "History command failed when trying to get the latest transaction of type "
87 | + transactionType;
88 | throw new IOException(msg);
89 | }
90 | if (transactionFound) {
91 | return transaction.get(0);
92 | } else {
93 | return null;
94 | }
95 | }
96 |
97 | /**
98 | * @param scm Accurev SCM
99 | * @param server server
100 | * @param accurevEnv Accurev Enviroment
101 | * @param workspace workspace
102 | * @param listener listener
103 | * @param launcher launcher
104 | * @param stream stream
105 | * @param lastTransaction lastTransaction
106 | * @return all the transaction for a given stream
107 | * @throws IOException if no transaction was found
108 | */
109 | public static List getTransactionsAfterLastTransaction( //
110 | final AccurevSCM scm, //
111 | final AccurevServer server, //
112 | final EnvVars accurevEnv, //
113 | final FilePath workspace, //
114 | final TaskListener listener, //
115 | final Launcher launcher, //
116 | final String stream,
117 | final int lastTransaction)
118 | throws IOException {
119 | // initialize code that extracts the latest transaction of a certain
120 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
121 | cmd.add("hist");
122 | addServer(cmd, server);
123 | cmd.add("-fx");
124 | cmd.add("-p");
125 | cmd.add(scm.getDepot());
126 | cmd.add("-s");
127 | cmd.add(stream);
128 | // Filter the history command to get all the transactions greater than the last transaction
129 | if (lastTransaction > 0) {
130 | cmd.add("-t");
131 | cmd.add("now-" + (lastTransaction + 1));
132 | }
133 | // execute code that extracts the latest transaction
134 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
135 | if (parser == null) {
136 | throw new IOException("No XML Parser");
137 | }
138 | final List transactions = new ArrayList<>();
139 | final Boolean transactionFound =
140 | AccurevLauncher.runHistCommandForAll(
141 | "History command",
142 | scm.getAccurevTool(),
143 | launcher,
144 | cmd,
145 | scm.getOptionalLock(workspace),
146 | accurevEnv,
147 | workspace,
148 | listener,
149 | logger,
150 | parser,
151 | new ParseHistory(),
152 | transactions);
153 | if (transactionFound == null) {
154 | throw new IOException("History command failed when trying to get all the transactionse ");
155 | }
156 | return transactions;
157 | }
158 |
159 | /**
160 | * @param scm Accurev SCM
161 | * @param server server
162 | * @param accurevEnv Accurev Enviroment
163 | * @param workspace workspace
164 | * @param listener listener
165 | * @param launcher launcher
166 | * @param stream stream
167 | * @param dateRange lastTransaction
168 | * @param transactionTypes
169 | * @return all the transaction for a given stream
170 | * @throws IOException if no transaction was found
171 | */
172 | public static List getTransactionsRange( //
173 | final AccurevSCM scm, //
174 | final AccurevServer server, //
175 | final EnvVars accurevEnv, //
176 | final FilePath workspace, //
177 | final TaskListener listener, //
178 | final Launcher launcher, //
179 | final String stream,
180 | final String transactionTypes,
181 | final String dateRange)
182 | throws IOException {
183 | // initialize code that extracts the latest transaction of a certain
184 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
185 | cmd.add("hist");
186 | addServer(cmd, server);
187 | cmd.add("-fx");
188 | cmd.add("-p");
189 | cmd.add(scm.getDepot());
190 | cmd.add("-s");
191 | cmd.add(stream);
192 | // Filter the history command to get all the transactions between last build date and now
193 | if (dateRange != null) {
194 | cmd.add("-t");
195 | cmd.add("now-" + (dateRange));
196 | }
197 |
198 | if (transactionTypes != null) {
199 | cmd.add("-k");
200 | cmd.add(transactionTypes);
201 | }
202 | // execute code that extracts the latest transaction
203 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
204 | if (parser == null) {
205 | throw new IOException("No XML Parser");
206 | }
207 | final List transactions = new ArrayList<>();
208 | final Boolean transactionFound =
209 | AccurevLauncher.runHistCommandForAll(
210 | "History command",
211 | scm.getAccurevTool(),
212 | launcher,
213 | cmd,
214 | scm.getOptionalLock(workspace),
215 | accurevEnv,
216 | workspace,
217 | listener,
218 | logger,
219 | parser,
220 | new ParseHistory(),
221 | transactions);
222 | if (transactionFound == null) {
223 | throw new IOException("History command failed when trying to get all the transactionse ");
224 | }
225 | return transactions;
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/CheckForChanges.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev;
2 |
3 | import hudson.EnvVars;
4 | import hudson.FilePath;
5 | import hudson.Launcher;
6 | import hudson.model.TaskListener;
7 | import hudson.plugins.accurev.AccurevSCM.AccurevServer;
8 | import hudson.plugins.accurev.cmd.History;
9 | import java.io.IOException;
10 | import java.text.SimpleDateFormat;
11 | import java.util.Arrays;
12 | import java.util.Collection;
13 | import java.util.Date;
14 | import java.util.HashSet;
15 | import java.util.List;
16 | import java.util.Set;
17 | import java.util.logging.Level;
18 | import java.util.logging.Logger;
19 | import org.apache.commons.collections.CollectionUtils;
20 | import org.apache.commons.io.FilenameUtils;
21 | import org.apache.commons.io.IOCase;
22 | import org.apache.commons.lang.StringUtils;
23 |
24 | public class CheckForChanges {
25 |
26 | /**
27 | * @param server server
28 | * @param accurevEnv accurev environment
29 | * @param workspace workspace
30 | * @param listener listener
31 | * @param launcher launcher
32 | * @param stream stream
33 | * @param buildDate build Date
34 | * @param logger logger
35 | * @param scm Accurev SCm
36 | * @param version
37 | * @return if there are any new transactions in the stream since the last build was done
38 | */
39 | // stream param is of type AccurevStream
40 | public static boolean checkStreamForChanges(
41 | AccurevServer server,
42 | EnvVars accurevEnv,
43 | FilePath workspace,
44 | TaskListener listener,
45 | Launcher launcher,
46 | AccurevStream stream,
47 | Date buildDate,
48 | Logger logger,
49 | AccurevSCM scm,
50 | int version) {
51 | String filterForPollSCM = scm.getFilterForPollSCM();
52 | String subPath = scm.getSubPath();
53 | List validTransactionTypes;
54 | if (stream.getType().name().equalsIgnoreCase("workspace")) {
55 | validTransactionTypes = AccurevSCM.DEFAULT_VALID_WORKSPACE_TRANSACTION_TYPES;
56 | } else {
57 | validTransactionTypes = AccurevSCM.DEFAULT_VALID_STREAM_TRANSACTION_TYPES;
58 | }
59 | String transactionTypes = String.join(",", validTransactionTypes);
60 | listener
61 | .getLogger()
62 | .println( //
63 | "Checking transactions of type "
64 | + transactionTypes
65 | + //
66 | " in stream ["
67 | + stream.getName()
68 | + "]");
69 | boolean isTransLatestThanBuild = false;
70 | Set serverPaths = new HashSet();
71 | Set pollingFilters = getListOfPollingFilters(filterForPollSCM, subPath);
72 |
73 | // AR version 7+ supports combined transaction type hist call.
74 | if (version < 7) {
75 | AccurevTransaction latestCodeChangeTransaction = new AccurevTransaction();
76 | latestCodeChangeTransaction.setDate(AccurevSCM.NO_TRANS_DATE);
77 |
78 | // query AccuRev for the latest transactions of each kind defined in transactionTypes using
79 | // getTimeOfLatestTransaction
80 | for (final String transactionType : validTransactionTypes) {
81 | try {
82 | final AccurevTransaction tempTransaction =
83 | History.getLatestTransaction(
84 | scm,
85 | server,
86 | accurevEnv,
87 | workspace,
88 | listener,
89 | launcher,
90 | stream.getName(),
91 | transactionType);
92 | if (tempTransaction != null) {
93 | listener
94 | .getLogger()
95 | .println(
96 | "Last transaction of type [" + transactionType + "] is " + tempTransaction);
97 |
98 | if (latestCodeChangeTransaction.getDate().before(tempTransaction.getDate())) {
99 | // check the affected
100 | serverPaths.addAll(tempTransaction.getAffectedPaths());
101 | if (tempTransaction.getAffectedPaths().size() > 0) {
102 | if (!changesMatchFilter(serverPaths, pollingFilters)) {
103 | // Continue to next transaction (that may have a match)
104 | continue;
105 | }
106 | }
107 | }
108 | latestCodeChangeTransaction = tempTransaction;
109 | if (latestCodeChangeTransaction.getDate().equals(AccurevSCM.NO_TRANS_DATE)) {
110 | listener.getLogger().println("No last transaction found.");
111 | }
112 | // log last transaction information if retrieved
113 | if (buildDate != null && buildDate.before(latestCodeChangeTransaction.getDate())) {
114 | listener.getLogger().println("Last valid trans " + latestCodeChangeTransaction);
115 | isTransLatestThanBuild = true;
116 | }
117 |
118 | } else {
119 | listener.getLogger().println("No transactions of type [" + transactionType + "]");
120 | }
121 | } catch (Exception e) {
122 | final String msg =
123 | "getLatestTransaction failed when checking the stream "
124 | + stream.getName()
125 | + " for changes with transaction type "
126 | + transactionType;
127 | listener.getLogger().println(msg);
128 | e.printStackTrace(listener.getLogger());
129 | logger.log(Level.WARNING, msg, e);
130 | }
131 | }
132 | return isTransLatestThanBuild;
133 | } else {
134 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
135 | String dateRange = formatter.format(buildDate);
136 |
137 | List tempTransaction;
138 | try {
139 | // history for all transaction types in time range from last build - now.
140 | tempTransaction =
141 | History.getTransactionsRange(
142 | scm,
143 | server,
144 | accurevEnv,
145 | workspace,
146 | listener,
147 | launcher,
148 | stream.getName(),
149 | transactionTypes,
150 | dateRange);
151 | if (!tempTransaction.isEmpty()) {
152 | for (AccurevTransaction t : tempTransaction) {
153 | if (t.getAffectedPaths().isEmpty()
154 | && (t.getAction().equals("mkstream")
155 | || t.getAction().equals("chstream")
156 | || t.getAction().equals("defcomp"))) {
157 | listener.getLogger().println("Last valid transaction " + tempTransaction);
158 | isTransLatestThanBuild = true;
159 | } else {
160 | serverPaths.addAll(t.getAffectedPaths());
161 | }
162 | }
163 | }
164 |
165 | if (serverPaths.size() > 0) {
166 | if (changesMatchFilter(serverPaths, pollingFilters)) {
167 | isTransLatestThanBuild = true;
168 | listener.getLogger().println("Last valid transaction " + tempTransaction);
169 | }
170 | }
171 | } catch (IOException e) {
172 |
173 | final String msg =
174 | "getLatestTransaction failed when checking the stream "
175 | + stream.getName()
176 | + " for changes with transaction type "
177 | + transactionTypes;
178 | listener.getLogger().println(msg);
179 | e.printStackTrace(listener.getLogger());
180 | logger.log(Level.WARNING, msg, e);
181 | }
182 | return isTransLatestThanBuild;
183 | }
184 | }
185 |
186 | public static boolean changesMatchFilter(
187 | Collection serverPaths, Collection filters) {
188 | if (CollectionUtils.isEmpty(filters)) {
189 | // No filters, so always a match.
190 | return true;
191 | }
192 |
193 | for (String path : serverPaths) {
194 | path = sanitizeSlashes(path);
195 | for (String filter : filters) {
196 | if (pathMatcher(path, filter)) {
197 | return true;
198 | }
199 | }
200 | }
201 | return false;
202 | }
203 |
204 | public static boolean pathMatcher(String path, String wildcard) {
205 | return FilenameUtils.wildcardMatch(path, wildcard, IOCase.INSENSITIVE);
206 | }
207 |
208 | private static Set getListOfPollingFilters(String filterForPollSCM, String subPath) {
209 | if (StringUtils.isNotBlank(filterForPollSCM)) {
210 | return splitAndSanitizeFilters(filterForPollSCM);
211 | }
212 |
213 | return splitAndSanitizeFilters(subPath);
214 | }
215 |
216 | private static Set splitAndSanitizeFilters(String input) {
217 | if (StringUtils.isBlank(input)) {
218 | return null;
219 | }
220 |
221 | final char DELIMITER = ',';
222 | final String STRIP_CHARS = " \t\n\r/";
223 | String[] filters = StringUtils.split(sanitizeSlashes(input), DELIMITER);
224 | filters = StringUtils.stripAll(filters, STRIP_CHARS);
225 |
226 | return new HashSet<>(Arrays.asList(filters));
227 | }
228 |
229 | private static String sanitizeSlashes(String input) {
230 | return input.replace('\\', '/');
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/delegates/ReftreeDelegate.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.delegates;
2 |
3 | import hudson.model.Job;
4 | import hudson.model.Run;
5 | import hudson.plugins.accurev.AccurevLauncher;
6 | import hudson.plugins.accurev.AccurevReferenceTree;
7 | import hudson.plugins.accurev.AccurevSCM;
8 | import hudson.plugins.accurev.DetermineRemoteHostname;
9 | import hudson.plugins.accurev.RemoteWorkspaceDetails;
10 | import hudson.plugins.accurev.XmlConsolidateStreamChangeLog;
11 | import hudson.plugins.accurev.XmlParserFactory;
12 | import hudson.plugins.accurev.cmd.Command;
13 | import hudson.plugins.accurev.cmd.Update;
14 | import hudson.plugins.accurev.delegates.Relocation.RelocationOption;
15 | import hudson.plugins.accurev.parsers.xml.ParseShowReftrees;
16 | import hudson.scm.PollingResult;
17 | import hudson.util.ArgumentListBuilder;
18 | import java.io.File;
19 | import java.io.IOException;
20 | import java.util.ArrayList;
21 | import java.util.List;
22 | import java.util.Map;
23 | import java.util.logging.Logger;
24 | import org.apache.commons.lang.StringUtils;
25 | import org.xmlpull.v1.XmlPullParserFactory;
26 |
27 | /** @author raymond */
28 | public class ReftreeDelegate extends AbstractModeDelegate {
29 |
30 | private static final Logger logger = Logger.getLogger(ReftreeDelegate.class.getName());
31 | protected boolean popRequired = false;
32 | private File updateLogFile;
33 |
34 | public ReftreeDelegate(AccurevSCM scm) {
35 | super(scm);
36 | }
37 |
38 | public String getSCMRefTree() {
39 | return scm.getReftree();
40 | }
41 |
42 | @Override
43 | protected PollingResult checkForChanges(Job, ?> project)
44 | throws IOException, InterruptedException {
45 | try {
46 | Relocation relocation = checkForRelocation();
47 | if (relocation.isRelocationRequired()) {
48 | listener.getLogger().println("Relocation required triggering build");
49 | return PollingResult.BUILD_NOW;
50 | } else {
51 | if (Update.hasChanges(
52 | scm, server, accurevEnv, accurevWorkingSpace, listener, launcher, getSCMRefTree())) {
53 | return PollingResult.BUILD_NOW;
54 | } else {
55 | return PollingResult.NO_CHANGES;
56 | }
57 | }
58 | } catch (IllegalArgumentException ex) {
59 | listener.fatalError(ex.getMessage());
60 | return PollingResult.NO_CHANGES;
61 | }
62 | }
63 |
64 | protected Relocation checkForRelocation() throws IOException, InterruptedException {
65 | final Map reftrees = getReftrees();
66 | String reftree = scm.getReftree();
67 | if (reftrees == null) {
68 | throw new IllegalArgumentException(
69 | "Cannot determine reference tree configuration information");
70 | }
71 | if (!reftrees.containsKey(reftree)) {
72 | throw new IllegalArgumentException("The specified reference tree does not appear to exist!");
73 | }
74 | AccurevReferenceTree accurevReftree = reftrees.get(reftree);
75 | if (!scm.getDepot().equals(accurevReftree.getDepot())) {
76 | throw new IllegalArgumentException(
77 | "The specified reference tree, "
78 | + reftree
79 | + ", is based in the depot "
80 | + accurevReftree.getDepot()
81 | + " not "
82 | + scm.getDepot());
83 | }
84 |
85 | RemoteWorkspaceDetails remoteDetails = getRemoteWorkspaceDetails();
86 |
87 | List relocationOptions = new ArrayList<>();
88 |
89 | for (RefTreeRelocation refTreeRelocation : RefTreeRelocation.values()) {
90 | if (refTreeRelocation.isRequired(accurevReftree, remoteDetails)) {
91 | relocationOptions.add(refTreeRelocation);
92 | }
93 | }
94 | return new Relocation(
95 | relocationOptions, remoteDetails.getHostName(), accurevWorkingSpace.getRemote(), null);
96 | }
97 |
98 | protected RemoteWorkspaceDetails getRemoteWorkspaceDetails() throws InterruptedException {
99 | try {
100 | return jenkinsWorkspace.act(new DetermineRemoteHostname(accurevWorkingSpace.getRemote()));
101 | } catch (IOException e) {
102 | e.printStackTrace(listener.getLogger());
103 | throw new IllegalArgumentException("Unable to validate reference tree host.");
104 | }
105 | }
106 |
107 | /**
108 | * Builds a command which gets executed and retrieves the following return data
109 | *
110 | * @return Map with Reference Tree name as key and Reference Tree Object as value.
111 | * @throws IOException Failed to execute command or Parse data.
112 | */
113 | private Map getReftrees() throws IOException {
114 | listener.getLogger().println("Getting a list of reference trees...");
115 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
116 | cmd.add("show");
117 | Command.addServer(cmd, server);
118 | cmd.add("-fx");
119 | cmd.add("refs");
120 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
121 | if (parser == null) {
122 | throw new IOException("No XML Parser");
123 | }
124 | return AccurevLauncher.runCommand(
125 | "Show ref trees command",
126 | scm.getAccurevTool(),
127 | launcher,
128 | cmd,
129 | scm.getOptionalLock(jenkinsWorkspace),
130 | accurevEnv,
131 | jenkinsWorkspace,
132 | listener,
133 | logger,
134 | parser,
135 | new ParseShowReftrees(),
136 | null);
137 | }
138 |
139 | @Override
140 | protected boolean checkout(Run, ?> build, File changeLogFile)
141 | throws IOException, InterruptedException {
142 | if (!validateCheckout(build)) {
143 | return false;
144 | }
145 | Relocation relocation = checkForRelocation();
146 | if (relocation.isRelocationRequired()) {
147 | if (!relocate(relocation)) {
148 | return false;
149 | }
150 | if (!populate(build, popRequired)) {
151 | return false;
152 | }
153 | }
154 |
155 | return doUpdate(changeLogFile);
156 | }
157 |
158 | private boolean doUpdate(File changeLogFile) throws IOException {
159 | updateLogFile = XmlConsolidateStreamChangeLog.getUpdateChangeLogFile(changeLogFile);
160 | return Update.performUpdate(
161 | scm,
162 | server,
163 | accurevEnv,
164 | accurevWorkingSpace,
165 | listener,
166 | launcher,
167 | getSCMRefTree(),
168 | updateLogFile);
169 | }
170 |
171 | @Override
172 | protected String getUpdateFileName() {
173 | return updateLogFile.getName();
174 | }
175 |
176 | protected String getPopulateFromMessage() {
177 | return "from reftree";
178 | }
179 |
180 | @Override
181 | protected String getPopulateStream() {
182 | return null;
183 | }
184 |
185 | private boolean relocate(Relocation relocation) throws IOException, InterruptedException {
186 | ArgumentListBuilder relocateCommand = getRelocateCommand();
187 | popRequired = relocation.isPopRequired();
188 | if (popRequired) {
189 | listener.getLogger().println("Clearing path: " + accurevWorkingSpace.getRemote());
190 | accurevWorkingSpace.deleteContents();
191 | }
192 | relocation.appendCommands(relocateCommand);
193 |
194 | return AccurevLauncher.runCommand(
195 | "relocation command",
196 | scm.getAccurevTool(),
197 | launcher,
198 | relocateCommand,
199 | scm.getOptionalLock(accurevWorkingSpace),
200 | accurevEnv,
201 | accurevWorkingSpace,
202 | listener,
203 | logger,
204 | true);
205 | }
206 |
207 | protected ArgumentListBuilder getRelocateCommand() {
208 | ArgumentListBuilder chrefcmd = new ArgumentListBuilder();
209 | chrefcmd.add("chref");
210 | Command.addServer(chrefcmd, server);
211 | chrefcmd.add("-r");
212 | chrefcmd.add(getSCMRefTree());
213 | return chrefcmd;
214 | }
215 |
216 | protected boolean validateCheckout(Run, ?> build) {
217 | String reftree = getSCMRefTree();
218 | if (StringUtils.isEmpty(reftree)) {
219 | listener.fatalError("Must specify a reference tree");
220 | return false;
221 | }
222 | return true;
223 | }
224 |
225 | @Override
226 | protected void buildEnvVarsCustom(Run, ?> build, Map env) {
227 | env.put("ACCUREV_REFTREE", scm.getReftree());
228 | }
229 |
230 | private enum RefTreeRelocation implements RelocationOption {
231 | HOST {
232 | @Override
233 | protected boolean isRequired(
234 | AccurevReferenceTree accurevReftree, RemoteWorkspaceDetails remoteDetails) {
235 | return !accurevReftree.getHost().equals(remoteDetails.getHostName());
236 | }
237 |
238 | public void appendCommand(ArgumentListBuilder cmd, Relocation relocation) {
239 | cmd.add("-m");
240 | cmd.add(relocation.getNewHost());
241 | }
242 | },
243 | STORAGE {
244 | @Override
245 | protected boolean isRequired(
246 | AccurevReferenceTree accurevReftree, RemoteWorkspaceDetails remoteDetails) {
247 | String oldStorage =
248 | accurevReftree
249 | .getStorage()
250 | .replace("/", remoteDetails.getFileSeparator())
251 | .replace("\\", remoteDetails.getFileSeparator());
252 | return !new File(oldStorage).equals(new File(remoteDetails.getPath()));
253 | }
254 |
255 | public void appendCommand(ArgumentListBuilder cmd, Relocation relocation) {
256 | cmd.add("-l");
257 | cmd.add(relocation.getNewPath());
258 | }
259 | };
260 |
261 | public boolean isPopRequired() {
262 | return true;
263 | }
264 |
265 | protected abstract boolean isRequired(
266 | AccurevReferenceTree accurevReftree, RemoteWorkspaceDetails remoteDetails);
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/src/main/java/hudson/plugins/accurev/delegates/WorkspaceDelegate.java:
--------------------------------------------------------------------------------
1 | package hudson.plugins.accurev.delegates;
2 |
3 | import hudson.model.Job;
4 | import hudson.model.Run;
5 | import hudson.plugins.accurev.AccurevLauncher;
6 | import hudson.plugins.accurev.AccurevSCM;
7 | import hudson.plugins.accurev.AccurevStream;
8 | import hudson.plugins.accurev.AccurevWorkspace;
9 | import hudson.plugins.accurev.RemoteWorkspaceDetails;
10 | import hudson.plugins.accurev.XmlParserFactory;
11 | import hudson.plugins.accurev.cmd.Command;
12 | import hudson.plugins.accurev.cmd.ShowStreams;
13 | import hudson.plugins.accurev.delegates.Relocation.RelocationOption;
14 | import hudson.plugins.accurev.parsers.xml.ParseShowWorkspaces;
15 | import hudson.scm.PollingResult;
16 | import hudson.util.ArgumentListBuilder;
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 | import java.util.Map;
22 | import java.util.logging.Logger;
23 | import org.apache.commons.lang.StringUtils;
24 | import org.xmlpull.v1.XmlPullParserFactory;
25 |
26 | /** @author raymond */
27 | public class WorkspaceDelegate extends ReftreeDelegate {
28 |
29 | private static final Logger logger = Logger.getLogger(WorkspaceDelegate.class.getName());
30 |
31 | public WorkspaceDelegate(AccurevSCM scm) {
32 | super(scm);
33 | }
34 |
35 | @Override
36 | public String getSCMRefTree() {
37 | return null;
38 | }
39 |
40 | @Override
41 | protected PollingResult checkForChanges(Job, ?> project)
42 | throws IOException, InterruptedException, IllegalArgumentException {
43 | localStream = scm.getPollingStream(project, listener);
44 | return super.checkForChanges(project);
45 | }
46 |
47 | @Override
48 | protected Relocation checkForRelocation() throws IOException, InterruptedException {
49 | String depot = scm.getDepot();
50 | String _accurevWorkspace = scm.getWorkspace();
51 | Map workspaces = getWorkspaces();
52 | Map streams =
53 | ShowStreams.getStreams(
54 | scm, _accurevWorkspace, server, accurevEnv, jenkinsWorkspace, listener, launcher);
55 |
56 | if (workspaces == null) {
57 | throw new IllegalArgumentException("Cannot determine workspace configuration information");
58 | }
59 | if (!workspaces.containsKey(_accurevWorkspace)) {
60 | throw new IllegalArgumentException("The specified workspace does not appear to exist!");
61 | }
62 | AccurevWorkspace accurevWorkspace = workspaces.get(_accurevWorkspace);
63 | if (!depot.equals(accurevWorkspace.getDepot())) {
64 | throw new IllegalArgumentException(
65 | "The specified workspace, "
66 | + _accurevWorkspace
67 | + ", is based in the depot "
68 | + accurevWorkspace.getDepot()
69 | + " not "
70 | + depot);
71 | }
72 |
73 | if (scm.isIgnoreStreamParent()) {
74 | if (!streams.isEmpty()) {
75 | AccurevStream workspaceStream = streams.values().iterator().next();
76 | accurevWorkspace.setStream(workspaceStream);
77 | String workspaceBasisStream = workspaceStream.getBasisName();
78 | if (streams.containsKey(workspaceBasisStream)) {
79 | workspaceStream.setParent(streams.get(workspaceBasisStream));
80 | } else {
81 | Map workspaceBasis =
82 | ShowStreams.getStreams(
83 | scm,
84 | workspaceBasisStream,
85 | server,
86 | accurevEnv,
87 | jenkinsWorkspace,
88 | listener,
89 | launcher);
90 | if (workspaceBasis == null) {
91 | throw new IllegalArgumentException("Could not determine the workspace basis stream");
92 | }
93 | workspaceStream.setParent(workspaceBasis.get(workspaceBasisStream));
94 | }
95 | } else {
96 | throw new IllegalArgumentException("Workspace stream not found " + _accurevWorkspace);
97 | }
98 | } else {
99 | for (AccurevStream accurevStream : streams.values()) {
100 | if (accurevWorkspace.getStreamNumber().equals(accurevStream.getNumber())) {
101 | accurevWorkspace.setStream(accurevStream);
102 | break;
103 | }
104 | }
105 | }
106 |
107 | final RemoteWorkspaceDetails remoteDetails = getRemoteWorkspaceDetails();
108 |
109 | List relocationOptions = new ArrayList<>();
110 | for (WorkspaceRelocation workspaceRelocationvalue : WorkspaceRelocation.values()) {
111 | if (workspaceRelocationvalue.isRequired(accurevWorkspace, remoteDetails, localStream)) {
112 | relocationOptions.add(workspaceRelocationvalue);
113 | }
114 | }
115 | return new Relocation(
116 | relocationOptions,
117 | remoteDetails.getHostName(),
118 | accurevWorkingSpace.getRemote(),
119 | localStream);
120 | }
121 |
122 | /**
123 | * Builds a command which gets executed and retrieves the following return data
124 | *
125 | * @return Map with Workspace name as key and Workspace Object as value.
126 | * @throws IOException Failed to execute command or Parse data.
127 | */
128 | private Map getWorkspaces() throws IOException {
129 | listener.getLogger().println("Getting a list of workspaces...");
130 | String depot = scm.getDepot();
131 | final ArgumentListBuilder cmd = new ArgumentListBuilder();
132 | cmd.add("show");
133 | Command.addServer(cmd, server);
134 | cmd.add("-fx");
135 | cmd.add("-p");
136 | cmd.add(depot);
137 | cmd.add("wspaces");
138 | XmlPullParserFactory parser = XmlParserFactory.getFactory();
139 | if (parser == null) {
140 | throw new IOException("No XML Parser");
141 | }
142 | return AccurevLauncher.runCommand(
143 | "Show workspaces command",
144 | scm.getAccurevTool(),
145 | launcher,
146 | cmd,
147 | scm.getOptionalLock(jenkinsWorkspace),
148 | accurevEnv,
149 | jenkinsWorkspace,
150 | listener,
151 | logger,
152 | parser,
153 | new ParseShowWorkspaces(),
154 | null);
155 | }
156 |
157 | @Override
158 | protected boolean validateCheckout(Run, ?> build) {
159 | String workspace = scm.getWorkspace();
160 | if (StringUtils.isEmpty(workspace)) {
161 | listener.fatalError("Must specify a workspace");
162 | return false;
163 | }
164 | return true;
165 | }
166 |
167 | @Override
168 | protected String getPopulateFromMessage() {
169 | return "from workspace";
170 | }
171 |
172 | @Override
173 | protected ArgumentListBuilder getRelocateCommand() {
174 | ArgumentListBuilder chwscmd = new ArgumentListBuilder();
175 | chwscmd.add("chws");
176 | Command.addServer(chwscmd, server);
177 | chwscmd.add("-w");
178 | chwscmd.add(scm.getWorkspace());
179 | return chwscmd;
180 | }
181 |
182 | @Override
183 | protected boolean isSteamColorEnabled() {
184 | return true;
185 | }
186 |
187 | @Override
188 | protected String getStreamColorStream() {
189 | return scm.getWorkspace();
190 | }
191 |
192 | @Override
193 | protected String getStreamColor() {
194 | return "#FFEBB4";
195 | }
196 |
197 | @Override
198 | protected String getChangeLogStream() {
199 | return scm.getWorkspace();
200 | }
201 |
202 | @Override
203 | protected void buildEnvVarsCustom(Run, ?> build, Map env) {
204 | env.put("ACCUREV_WORKSPACE", scm.getWorkspace());
205 | }
206 |
207 | private enum WorkspaceRelocation implements RelocationOption {
208 | HOST {
209 | @Override
210 | protected boolean isRequired(
211 | AccurevWorkspace accurevWorkspace,
212 | RemoteWorkspaceDetails remoteDetails,
213 | String localStream) {
214 | return !accurevWorkspace.getHost().equalsIgnoreCase(remoteDetails.getHostName());
215 | }
216 |
217 | public void appendCommand(ArgumentListBuilder cmd, Relocation relocation) {
218 | cmd.add("-m");
219 | cmd.add(relocation.getNewHost());
220 | }
221 | },
222 | STORAGE {
223 | @Override
224 | protected boolean isRequired(
225 | AccurevWorkspace accurevWorkspace,
226 | RemoteWorkspaceDetails remoteDetails,
227 | String localStream) {
228 | String oldStorage =
229 | accurevWorkspace
230 | .getStorage()
231 | .replace("/", remoteDetails.getFileSeparator())
232 | .replace("\\", remoteDetails.getFileSeparator());
233 | return !new File(oldStorage).equals(new File(remoteDetails.getPath()));
234 | }
235 |
236 | public void appendCommand(ArgumentListBuilder cmd, Relocation relocation) {
237 | cmd.add("-l");
238 | cmd.add(relocation.getNewPath());
239 | }
240 | },
241 | REPARENT {
242 | @Override
243 | protected boolean isRequired(
244 | AccurevWorkspace accurevWorkspace,
245 | RemoteWorkspaceDetails remoteDetails,
246 | String localStream) {
247 | return !localStream.equals(accurevWorkspace.getStream().getParent().getName());
248 | }
249 |
250 | @Override
251 | public boolean isPopRequired() {
252 | return false;
253 | }
254 |
255 | public void appendCommand(ArgumentListBuilder cmd, Relocation relocation) {
256 | cmd.add("-b");
257 | cmd.add(relocation.getNewParent());
258 | }
259 | };
260 |
261 | public boolean isPopRequired() {
262 | return true;
263 | }
264 |
265 | protected abstract boolean isRequired(
266 | AccurevWorkspace accurevWorkspace,
267 | RemoteWorkspaceDetails remoteDetails,
268 | String localStream);
269 | }
270 | }
271 |
--------------------------------------------------------------------------------