[MAVEN-963] Add Perforce changelog support. Thanks to Jim Crossley
git-svn-id: https://svn.apache.org/repos/asf/maven/maven-1/plugins/trunk@114244 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b1332f6273
commit
68b8157191
@ -0,0 +1,119 @@
|
||||
package org.apache.maven.perforcelib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import org.apache.maven.changelog.ChangeLogFactory;
|
||||
import org.apache.maven.changelog.ChangeLogGenerator;
|
||||
import org.apache.maven.changelog.ChangeLogParser;
|
||||
|
||||
/**
|
||||
* Provides Perforce specific instances of the ChangeLogGenerator and
|
||||
* ChangeLogParser interfaces.
|
||||
*
|
||||
* It expects the repository connection element in the POM to be of
|
||||
* this form: <b><code>scm:perforce[:P4PORT]:FILESPEC</code></b>. If
|
||||
* the P4PORT is omitted, the corresponding environment variable will
|
||||
* be used. The FILESPEC should use the appropriate Perforce
|
||||
* wildcards to represent all of the project's files. For example,
|
||||
*
|
||||
* <pre>
|
||||
* <repository>
|
||||
* <connection>
|
||||
* scm:perforce:some.host.com:1666://depot/projects/maven/...
|
||||
* </connection>
|
||||
* <url>
|
||||
* http://public.perforce.com:8080
|
||||
* </url>
|
||||
* </repository>
|
||||
* </pre>
|
||||
*
|
||||
* The repository url element should reference the root context of a <a
|
||||
* href="http://www.perforce.com/perforce/products/p4web.html">p4web</a>
|
||||
* instance.
|
||||
*
|
||||
* @author <a href="mailto:jim@crossleys.org">Jim Crossley</a>
|
||||
* @version $Id:
|
||||
*/
|
||||
public class PerforceChangeLogFactory implements ChangeLogFactory
|
||||
{
|
||||
/**
|
||||
* Default no-arg constructor.
|
||||
*/
|
||||
public PerforceChangeLogFactory()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Perforce specific ChangeLogGenerator.
|
||||
*
|
||||
* @return a Perforce specific ChangeLogGenerator.
|
||||
*/
|
||||
public ChangeLogGenerator createGenerator()
|
||||
{
|
||||
return new PerforceChangeLogGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Perforce specific ChangeLogParser.
|
||||
*
|
||||
* @return a Perforce specific ChangeLogParser.
|
||||
*/
|
||||
public ChangeLogParser createParser()
|
||||
{
|
||||
return new PerforceChangeLogParser();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,151 @@
|
||||
package org.apache.maven.perforcelib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.maven.changelog.AbstractChangeLogGenerator;
|
||||
import org.apache.tools.ant.types.Commandline;
|
||||
|
||||
/**
|
||||
* A Perforce implementation of the {@link org.apache.maven.changelog.ChangeLog}
|
||||
* interface.
|
||||
*
|
||||
* @author <a href="mailto:jim@crossleys.org">Jim Crossley</a>
|
||||
* @version $Id:
|
||||
*/
|
||||
class PerforceChangeLogGenerator extends AbstractChangeLogGenerator
|
||||
{
|
||||
/** The position after the connection prefix, 'scm:perforce:' */
|
||||
private static final int POS_PARAMS = 13;
|
||||
|
||||
/** Log */
|
||||
private static final Log LOG = LogFactory.getLog(PerforceChangeLogGenerator.class);
|
||||
|
||||
/**
|
||||
* Constructs the appropriate command line to execute the perforce
|
||||
* log command whose output is then later parsed.
|
||||
*
|
||||
* Repository connection syntax:
|
||||
* scm:perforce[:host:port]://depot/projects/name/...
|
||||
*
|
||||
* @return the cvs command line to be executed.
|
||||
*/
|
||||
protected Commandline getScmLogCommand()
|
||||
{
|
||||
String conn = getConnection();
|
||||
if (!conn.startsWith("scm:perforce:"))
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"repository connection string"
|
||||
+ " does not specify 'perforce' as the scm");
|
||||
}
|
||||
int lastColon = conn.lastIndexOf(':');
|
||||
String fileSpec = conn.substring(lastColon+1);
|
||||
String p4port = (POS_PARAMS>lastColon) ? null : conn.substring(POS_PARAMS, lastColon);
|
||||
|
||||
Commandline command = new Commandline();
|
||||
command.setExecutable("p4");
|
||||
if (p4port != null) {
|
||||
command.createArgument().setValue("-p");
|
||||
command.createArgument().setValue(p4port);
|
||||
}
|
||||
command.createArgument().setValue("filelog");
|
||||
command.createArgument().setValue("-tl");
|
||||
command.createArgument().setValue(fileSpec);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Perforce filelog doesn't support a revision, i.e. date,
|
||||
* range
|
||||
*
|
||||
* @param before The starting point.
|
||||
* @param to The ending point.
|
||||
* @return An empty string
|
||||
*/
|
||||
protected String getScmDateArgument(Date before, Date to)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ChangeLogParser IOExceptions.
|
||||
*
|
||||
* @param ioe The IOException thrown.
|
||||
* @throws IOException If the handler doesn't wish to handle the
|
||||
* exception.
|
||||
*/
|
||||
protected void handleParserException(IOException ioe)
|
||||
throws IOException
|
||||
{
|
||||
if (ioe.getMessage().indexOf("CreateProcess") != -1
|
||||
|| ioe.getMessage().indexOf("p4: not found") != -1)
|
||||
{
|
||||
// can't find p4 on Win32 or Linux...
|
||||
LOG.error(
|
||||
"Unable to find p4 executable. Changelog will be empty");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,305 @@
|
||||
package org.apache.maven.perforcelib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.ArrayList;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.maven.changelog.ChangeLog;
|
||||
import org.apache.maven.changelog.ChangeLogParser;
|
||||
import org.apache.maven.changelog.ChangeLogEntry;
|
||||
import org.apache.maven.changelog.ChangeLogFile;
|
||||
import org.apache.regexp.RE;
|
||||
import org.apache.regexp.RESyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* A class to parse the log output from the Perforce 'filelog'
|
||||
* command.
|
||||
*
|
||||
* @author <a href="mailto:jim@crossleys.org">Jim Crossley</a>
|
||||
* @version $Id:
|
||||
*/
|
||||
class PerforceChangeLogParser implements ChangeLogParser
|
||||
{
|
||||
/** Date formatter for perforce timestamp */
|
||||
private static final SimpleDateFormat PERFORCE_TIMESTAMP =
|
||||
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
|
||||
|
||||
/** Log */
|
||||
private static final Log LOG = LogFactory.getLog (PerforceChangeLogParser.class);
|
||||
|
||||
/**
|
||||
* RCS entries, in reverse changelist number order
|
||||
*/
|
||||
private Map entries = new TreeMap(Collections.reverseOrder());
|
||||
|
||||
/** State machine constant: expecting revision and/or file information */
|
||||
private static final int GET_REVISION = 1;
|
||||
|
||||
/** State machine constant: eat the first blank line */
|
||||
private static final int GET_COMMENT_BEGIN = 2;
|
||||
|
||||
/** State machine constant: expecting comments */
|
||||
private static final int GET_COMMENT = 3;
|
||||
|
||||
/** The comment section ends with a blank line */
|
||||
private static final String COMMENT_DELIMITER = "";
|
||||
|
||||
/** A file line begins with two slashes */
|
||||
private static final String FILE_BEGIN_TOKEN = "//";
|
||||
|
||||
/** Current status of the parser */
|
||||
private int status = GET_REVISION;
|
||||
|
||||
/** The current log entry being processed by the parser */
|
||||
private ChangeLogEntry currentLogEntry;
|
||||
|
||||
/** the current file being processed by the parser */
|
||||
private String currentFile;
|
||||
|
||||
/** The regular expression used to match header lines */
|
||||
private RE revisionRegexp;
|
||||
|
||||
/** The invoking changelog controller (useful to log messages) */
|
||||
private ChangeLog changeLog;
|
||||
|
||||
/** the before date */
|
||||
private Date beforeDate;
|
||||
|
||||
private static final String pattern =
|
||||
"^\\.\\.\\. #(\\d+) " + // revision number
|
||||
"change (\\d+) .* " + // changelist number
|
||||
"on (.*) " + // date
|
||||
"by (.*)@"; // author
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public PerforceChangeLogParser()
|
||||
{
|
||||
try {
|
||||
revisionRegexp = new RE(pattern);
|
||||
} catch (RESyntaxException ignored) {
|
||||
LOG.error("Could not create regexp to parse perforce log file", ignored);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the parser from the change log.
|
||||
*
|
||||
* @param changeLog The controlling task
|
||||
* @see ChangeLogParser#init(ChangeLog)
|
||||
*/
|
||||
public void init(ChangeLog changeLog)
|
||||
{
|
||||
this.changeLog = changeLog;
|
||||
setDateRange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up any parser resources.
|
||||
*
|
||||
* @see ChangeLogParser#cleanup()
|
||||
*/
|
||||
public void cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the input stream into a collection of entries
|
||||
*
|
||||
* @param anInputStream An input stream containing perforce log output
|
||||
* @return A collection of ChangeLogEntry's
|
||||
* @throws IOException When there are errors reading the provided stream
|
||||
*/
|
||||
public Collection parse(InputStream anInputStream) throws IOException
|
||||
{
|
||||
BufferedReader stream = new BufferedReader(new InputStreamReader(anInputStream));
|
||||
|
||||
String line = null;
|
||||
while ((line = stream.readLine()) != null)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case GET_REVISION:
|
||||
processGetRevision(line);
|
||||
break;
|
||||
case GET_COMMENT_BEGIN:
|
||||
status = GET_COMMENT;
|
||||
break;
|
||||
case GET_COMMENT:
|
||||
processGetComment(line);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown state: " + status);
|
||||
}
|
||||
}
|
||||
return entries.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a change log entry to the list (if it's not already there)
|
||||
* with the given file.
|
||||
* @param entry a {@link ChangeLogEntry} to be added to the list if another
|
||||
* with the same key (p4 change number) doesn't exist already.
|
||||
* @param file a {@link ChangeLogFile} to be added to the entry
|
||||
*/
|
||||
private void addEntry(ChangeLogEntry entry, ChangeLogFile file)
|
||||
{
|
||||
System.out.println();
|
||||
System.out.println(entry.toXML());
|
||||
if (beforeDate != null) {
|
||||
if (entry.getDate().before(beforeDate)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Integer key = new Integer(revisionRegexp.getParen(2));
|
||||
if (!entries.containsKey(key)) {
|
||||
entry.addFile(file);
|
||||
entries.put(key, entry);
|
||||
} else {
|
||||
ChangeLogEntry existingEntry = (ChangeLogEntry) entries.get(key);
|
||||
existingEntry.addFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Most of the relevant info is on the revision line matching the
|
||||
* 'pattern' string.
|
||||
*
|
||||
* @param line A line of text from the perforce log output
|
||||
*/
|
||||
private void processGetRevision(String line)
|
||||
{
|
||||
if (line.startsWith(FILE_BEGIN_TOKEN)) {
|
||||
currentFile = line;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!revisionRegexp.match(line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentLogEntry = new ChangeLogEntry();
|
||||
currentLogEntry.setDate(parseDate(revisionRegexp.getParen(3)));
|
||||
currentLogEntry.setAuthor(revisionRegexp.getParen(4));
|
||||
|
||||
status = GET_COMMENT_BEGIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the current input line in the GET_COMMENT state. This
|
||||
* state gathers all of the comments that are part of a log entry.
|
||||
*
|
||||
* @param line a line of text from the perforce log output
|
||||
*/
|
||||
private void processGetComment(String line)
|
||||
{
|
||||
if (line.equals(COMMENT_DELIMITER)) {
|
||||
addEntry(currentLogEntry, new ChangeLogFile(currentFile, revisionRegexp.getParen(1)));
|
||||
status = GET_REVISION;
|
||||
} else {
|
||||
currentLogEntry.setComment(currentLogEntry.getComment() + line + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the date timestamp from the perforce output into a date
|
||||
* object.
|
||||
*
|
||||
* @return A date representing the timestamp of the log entry.
|
||||
*/
|
||||
private Date parseDate(String date)
|
||||
{
|
||||
try {
|
||||
return PERFORCE_TIMESTAMP.parse(date);
|
||||
} catch (ParseException e) {
|
||||
LOG.error("ParseException Caught", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the beforeDate member based on the number of days obtained
|
||||
* from the ChangeLog.
|
||||
*
|
||||
* @param numDaysString The number of days of log output to
|
||||
* generate.
|
||||
*/
|
||||
private void setDateRange()
|
||||
{
|
||||
if (this.changeLog == null ||
|
||||
this.changeLog.getRange() == null ||
|
||||
this.changeLog.getRange().length() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int days = Integer.parseInt(this.changeLog.getRange());
|
||||
beforeDate = new Date(System.currentTimeMillis() - (long) days * 24 * 60 * 60 * 1000);
|
||||
}
|
||||
}
|
||||
@ -60,8 +60,17 @@
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
|
||||
<j:choose>
|
||||
<j:when test="${pom.repository.connection.startsWith('scm:perforce')}">
|
||||
<a href="${repository}${name}?ac=22">${name}</a>
|
||||
<a href="${repository}${name}?ac=64&rev1=${revision}">v${revision}</a>
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
<a href="${repository}${name}${oneRepoParam}">${name}</a>
|
||||
<a href="${repository}${name}?rev=${revision}&content-type=text/vnd.viewcvs-markup${multiRepoParam}">v${revision}</a>
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
|
||||
<br/>
|
||||
|
||||
</x:forEach>
|
||||
|
||||
47
changelog/src/test-resources/perforcelib/perforcelog.txt
Normal file
47
changelog/src/test-resources/perforcelib/perforcelog.txt
Normal file
@ -0,0 +1,47 @@
|
||||
//depot/test/demo/demo.c
|
||||
... #4 change 7 edit on 2003/10/01 16:24:20 by jim@cpt-jcrossley (text)
|
||||
|
||||
Backing out my test changes
|
||||
|
||||
Updating a description
|
||||
|
||||
... #3 change 4 edit on 2003/10/01 08:35:08 by jim@cpt-jcrossley (text)
|
||||
|
||||
Another test
|
||||
|
||||
... #2 change 3 edit on 2003/10/01 08:29:15 by jim@cpt-jcrossley (text)
|
||||
|
||||
Testing review daemon
|
||||
|
||||
Updating description
|
||||
|
||||
... #1 change 1 add on 2003/08/07 17:21:57 by mcronin@mcronin (text)
|
||||
|
||||
demonstration of Perforce on Windows, Unix and VMS.
|
||||
|
||||
... ... branch into //depot/releases/test-1/demo/demo.c#1
|
||||
//depot/test/demo/dictcalls.txt
|
||||
... #1 change 1 add on 2003/08/07 17:21:57 by mcronin@mcronin (text)
|
||||
|
||||
demonstration of Perforce on Windows, Unix and VMS.
|
||||
|
||||
... ... branch into //depot/releases/test-1/demo/dictcalls.txt#1
|
||||
//depot/test/demo/dictwords.txt
|
||||
... #1 change 1 add on 2003/08/07 17:21:57 by mcronin@mcronin (text)
|
||||
|
||||
demonstration of Perforce on Windows, Unix and VMS.
|
||||
|
||||
... ... branch into //depot/releases/test-1/demo/dictwords.txt#1
|
||||
//depot/test/junk/linefeed.txt
|
||||
... #3 change 13 edit on 2003/10/15 13:38:40 by jim@cpt-jcrossley (text)
|
||||
|
||||
Where's my change #
|
||||
|
||||
... #2 change 10 edit on 2003/10/15 07:14:46 by jim@jcrossley (text)
|
||||
|
||||
Added a linefeed at the end to see if the [noeol] descriptor goes away in vim.
|
||||
|
||||
... #1 change 9 add on 2003/10/15 07:01:59 by jim@cpt-jcrossley (text)
|
||||
|
||||
Testing CR/LF resolution on different platforms
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
package org.apache.maven.perforcelib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2003 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
|
||||
import org.apache.maven.project.Repository;
|
||||
import org.apache.maven.util.EnhancedStringTokenizer;
|
||||
import org.apache.tools.ant.types.Commandline;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author <a href="jim@crossleys.org">Jim Crossley</a>
|
||||
* @author <a href="bwalding@jakarta.org">Ben Walding</a>
|
||||
* @version $Id:
|
||||
*/
|
||||
public class PerforceChangeLogGeneratorTest extends TestCase
|
||||
{
|
||||
class Test
|
||||
{
|
||||
String conn;
|
||||
String args;
|
||||
Class throwable;
|
||||
|
||||
public Test(String conn, String args, Class throwable)
|
||||
{
|
||||
this.conn = conn;
|
||||
this.args = args;
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Test[] tests =
|
||||
{
|
||||
new Test(null, "", NullPointerException.class),
|
||||
new Test("asd:asd", "", IllegalArgumentException.class),
|
||||
new Test("scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-turbine-maven",
|
||||
"",
|
||||
IllegalArgumentException.class),
|
||||
new Test("scm:perforce:host:port://depot/projects/name/...",
|
||||
"p4|-p|host:port|filelog|-tl|//depot/projects/name/...",
|
||||
null),
|
||||
new Test("scm:perforce:port://depot/projects/name/...",
|
||||
"p4|-p|port|filelog|-tl|//depot/projects/name/...",
|
||||
null),
|
||||
new Test("scm:perforce://depot/projects/name/...",
|
||||
"p4|filelog|-tl|//depot/projects/name/...",
|
||||
null),
|
||||
};
|
||||
|
||||
public void testParse() throws Throwable
|
||||
{
|
||||
for (int i = 0; i < tests.length; i++)
|
||||
{
|
||||
Test t = tests[i];
|
||||
testParse(t);
|
||||
}
|
||||
}
|
||||
|
||||
public void testParse(Test test) throws Throwable
|
||||
{
|
||||
String[] expected = Repository.tokenizerToArray(new EnhancedStringTokenizer(test.args, "|"));
|
||||
|
||||
PerforceChangeLogGenerator eg = new PerforceChangeLogGenerator();
|
||||
try {
|
||||
eg.setConnection(test.conn);
|
||||
Commandline cl = eg.getScmLogCommand();
|
||||
String[] clArgs = cl.getCommandline();
|
||||
if (test.throwable == null)
|
||||
{
|
||||
assertEquals("clArgs.length", expected.length, clArgs.length);
|
||||
for (int i = 0; i < expected.length; i++)
|
||||
{
|
||||
assertEquals("clArgs[" + i + "]", expected[i], clArgs[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fail("Failed to throw :" + test.throwable.getName());
|
||||
}
|
||||
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
if (test.throwable != null && test.throwable.isAssignableFrom(t.getClass()))
|
||||
{
|
||||
//Success
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Caught unexpected exception \"" + t.getLocalizedMessage() + "\" testing " + test.conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,167 @@
|
||||
package org.apache.maven.perforcelib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.maven.changelog.ChangeLogEntry;
|
||||
|
||||
/**
|
||||
* Test cases for {@link PerforceChangeLogParser}
|
||||
* @author <a href="mailto:jim@crossleys.org">Jim Crossley</a>
|
||||
* @version $Id:
|
||||
*/
|
||||
public class PerforceChangeLogParserTest extends TestCase
|
||||
{
|
||||
/** The {@link PerforceChangeLogParser} used for testing */
|
||||
private PerforceChangeLogParser parser;
|
||||
|
||||
/** File with test results to check against */
|
||||
private String testFile;
|
||||
|
||||
/**
|
||||
* Create a test with the given name.
|
||||
*
|
||||
* @param testName the name of the test.
|
||||
*/
|
||||
public PerforceChangeLogParserTest(String testName)
|
||||
{
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize per test data.
|
||||
*
|
||||
* @throws Exception when there is an unexpected problem.
|
||||
*/
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
String baseDir = System.getProperty("basedir");
|
||||
assertNotNull("The system property basedir was not defined.", baseDir);
|
||||
testFile = baseDir + "/src/test-resources/perforcelib/perforcelog.txt";
|
||||
parser = new PerforceChangeLogParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the Perforce parser.
|
||||
*
|
||||
* @throws Exception when there is an unexpected problem
|
||||
*/
|
||||
public void testParse() throws Exception
|
||||
{
|
||||
FileInputStream fis = new FileInputStream(testFile);
|
||||
List entries = new ArrayList(parser.parse(fis));
|
||||
|
||||
assertEquals("Wrong number of entries returned", 7, entries.size());
|
||||
|
||||
ChangeLogEntry entry = (ChangeLogEntry) entries.get(0);
|
||||
assertEquals("Entry 0 was parsed incorrectly",
|
||||
"\t<changelog-entry>\n" +
|
||||
"\t\t<date>2003-10-15</date>\n" +
|
||||
"\t\t<time>13:38:40</time>\n" +
|
||||
"\t\t<author><![CDATA[jim]]></author>\n" +
|
||||
"\t\t<file>\n" +
|
||||
"\t\t\t<name>//depot/test/junk/linefeed.txt</name>\n" +
|
||||
"\t\t\t<revision>3</revision>\n" +
|
||||
"\t\t</file>\n" +
|
||||
"\t\t<msg><![CDATA[ Where's my change #\n" +
|
||||
"]]></msg>\n" +
|
||||
"\t</changelog-entry>\n",
|
||||
entry.toXML());
|
||||
|
||||
entry = (ChangeLogEntry) entries.get(3);
|
||||
assertEquals("Entry 3 was parsed incorrectly",
|
||||
"\t<changelog-entry>\n" +
|
||||
"\t\t<date>2003-10-01</date>\n" +
|
||||
"\t\t<time>16:24:20</time>\n" +
|
||||
"\t\t<author><![CDATA[jim]]></author>\n" +
|
||||
"\t\t<file>\n" +
|
||||
"\t\t\t<name>//depot/test/demo/demo.c</name>\n" +
|
||||
"\t\t\t<revision>4</revision>\n" +
|
||||
"\t\t</file>\n" +
|
||||
"\t\t<msg><![CDATA[ Backing out my test changes\n" +
|
||||
"\t\n" +
|
||||
"\tUpdating a description\n" +
|
||||
"]]></msg>\n" +
|
||||
"\t</changelog-entry>\n",
|
||||
entry.toXML());
|
||||
|
||||
entry = (ChangeLogEntry) entries.get(6);
|
||||
assertEquals("Entry 6 was parsed incorrectly",
|
||||
"\t<changelog-entry>\n" +
|
||||
"\t\t<date>2003-08-07</date>\n" +
|
||||
"\t\t<time>17:21:57</time>\n" +
|
||||
"\t\t<author><![CDATA[mcronin]]></author>\n" +
|
||||
"\t\t<file>\n" +
|
||||
"\t\t\t<name>//depot/test/demo/demo.c</name>\n" +
|
||||
"\t\t\t<revision>1</revision>\n" +
|
||||
"\t\t</file>\n" +
|
||||
"\t\t<file>\n" +
|
||||
"\t\t\t<name>//depot/test/demo/dictcalls.txt</name>\n" +
|
||||
"\t\t\t<revision>1</revision>\n" +
|
||||
"\t\t</file>\n" +
|
||||
"\t\t<file>\n" +
|
||||
"\t\t\t<name>//depot/test/demo/dictwords.txt</name>\n" +
|
||||
"\t\t\t<revision>1</revision>\n" +
|
||||
"\t\t</file>\n" +
|
||||
"\t\t<msg><![CDATA[ demonstration of Perforce on Windows, Unix and VMS.\n" +
|
||||
"]]></msg>\n" +
|
||||
"\t</changelog-entry>\n",
|
||||
entry.toXML());
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,9 @@
|
||||
Added java based CVS library using cvslib. Removed
|
||||
requirement for cvs executable.
|
||||
</action>
|
||||
<action dev="jcrossley" type="update">
|
||||
MAVEN-963. Add support for Perforce SCM and cleaned up some docs.
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.3" date="2003-09-29">
|
||||
<action dev="dion" type="update">
|
||||
|
||||
@ -10,10 +10,11 @@
|
||||
<body>
|
||||
<section name="Maven Changelog Plug-in">
|
||||
<p>
|
||||
This plugin produces a nicely formatted changelog report so project
|
||||
team members can see at a glance what changes have been made
|
||||
recently to the project. Currently, there are three supported
|
||||
source control systems: CVS, StarTeam, IBM Rational ClearCase and Subversion.
|
||||
This plugin produces a nicely formatted changelog report so
|
||||
project team members can see at a glance what changes have
|
||||
been made recently to the project. Currently, there are five
|
||||
supported source control systems: CVS, Perforce, StarTeam, IBM
|
||||
Rational ClearCase and Subversion.
|
||||
</p>
|
||||
<p>
|
||||
For more information on the functionality provided by this plugin,
|
||||
|
||||
@ -7,7 +7,9 @@
|
||||
<links>
|
||||
<item name="Maven" href="http://maven.apache.org/"/>
|
||||
<item name="CVS" href="http://www.cvshome.org/"/>
|
||||
<item name="Perforce" href="http://www.perforce.com/"/>
|
||||
<item name="StarTeam" href="http://www.borland.com/starteam/"/>
|
||||
<item name="ClearCase" href="http://www.ibm.com/software/awdtools/clearcase/" />
|
||||
<item name="Subversion" href="http://subversion.tigris.org/" />
|
||||
</links>
|
||||
<menu name="Overview">
|
||||
|
||||
@ -33,19 +33,24 @@
|
||||
<td>Yes</td>
|
||||
<td>
|
||||
Specifies a fully qualified class name implementing the
|
||||
<code>org.apache.maven.changelog.ChangeLogFactory</code> interface.
|
||||
The class creates the <code>ChangeLogGenerator</code> and
|
||||
<code>ChangeLogParser</code> pair required to create the change
|
||||
log. This is used by the "changelog" and "activity" goals.
|
||||
The default value is <a
|
||||
href="../apidocs/org/apache/maven/cvslib/CvsChangeLogFactory.html">
|
||||
org.apache.maven.cvslib.CvsChangeLogFactory</a>. In
|
||||
addition, there is also a Subversion factory (<a
|
||||
href="../apidocs/org/apache/maven/svnlib/SvnChangeLogFactory.html">
|
||||
org.apache.maven.svnlib.SvnChangeLogFactory</a>) as well as
|
||||
a StarTeam factory (<a
|
||||
href="../apidocs/org/apache/maven/starteamlib/StarteamChangeLogFactory.html">
|
||||
org.apache.maven.starteamlib.StarteamChangeLogFactory</a>).
|
||||
<code>org.apache.maven.changelog.ChangeLogFactory</code>
|
||||
interface. The class creates the
|
||||
<code>ChangeLogGenerator</code> and
|
||||
<code>ChangeLogParser</code> pair required to create the
|
||||
change log. This is used by the "changelog" and
|
||||
"activity" goals. The following SCM factories are supported:
|
||||
<ul>
|
||||
<li>CVS (the default): <a
|
||||
href="apidocs/org/apache/maven/cvslib/CvsChangeLogFactory.html">org.apache.maven.cvslib.CvsChangeLogFactory</a></li>
|
||||
<li>Perforce: <a
|
||||
href="apidocs/org/apache/maven/perforcelib/PerforceChangeLogFactory.html">org.apache.maven.perforcelib.PerforceChangeLogFactory</a></li>
|
||||
<li>Subversion: <a
|
||||
href="apidocs/org/apache/maven/svnlib/SvnChangeLogFactory.html">org.apache.maven.svnlib.SvnChangeLogFactory</a></li>
|
||||
<li>Clearcase: <a
|
||||
href="apidocs/org/apache/maven/clearcaselib/ClearcaseChangeLogFactory.html">org.apache.maven.clearcaselib.ClearcaseChangeLogFactory</a></li>
|
||||
<li>StarTeam: <a
|
||||
href="apidocs/org/apache/maven/starteamlib/StarteamChangeLogFactory.html">org.apache.maven.starteamlib.StarteamChangeLogFactory</a></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@ -48,7 +48,14 @@
|
||||
<j:set var="oneRepoParam" value=""/>
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
<j:choose>
|
||||
<j:when test="${pom.repository.connection.startsWith('scm:perforce')}">
|
||||
<j:set var="urlFile" value="${repository.trim()}${name.trim()}?ac=22"/>
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
<j:set var="urlFile" value="${repository.trim()}${name.trim()}${oneRepoParam.trim()}"/>
|
||||
</j:otherwise>
|
||||
</j:choose>
|
||||
<a href="${urlFile}">${name}</a>
|
||||
</j:when>
|
||||
<j:otherwise>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user