0

在我正在进行的项目中,我们并行开发了各种多模块项目,其中一些项目依赖于其他项目。因此,我们使用版本范围,例如[0.0.1,),用于开发期间的内部依赖项,以便我们始终可以针对最新的快照版本工作。(我知道这不是最佳实践,但至少现在我们仍然坚持当前的项目结构。)我们已经设置了构建配置文件,因此当我们执行发布时,所有版本范围都被替换RELEASE为编译最新发布的版本。

我们必须使用范围,而不是LATEST因为在本地安装工件时,<latest>maven-metadata-local.xml 中的标签永远不会更新,因此指定LATEST将获得部署到我们的 Artifactory 服务器的最后一个版本。但是,范围的问题在于构建过程似乎必须下载工件所有版本的所有元数据文件才能确定最新版本。随着我们项目的进行,我们正在积累越来越多的版本和工件,因此我们的构建时间越来越长。指定LATEST可以避免这种情况,但意味着通常不会提取来自本地工件安装的更改。

<latest>在本地安装工件时,有什么方法可以更新 maven-metadata-local.xml 文件中的标签?

4

3 回答 3

1

我有同样的问题,所以我写了一个 maven 插件来为我处理它。这是一个非常极端的解决方法,但它确实有效。

创建 Maven 插件的文档位于The Apache Maven Project上。您可以从命令行原型创建一个插件项目并将这个 mojo 添加到您的项目中。

/**
 * Inserts a "latest" block into the maven-metadata-local.xml in the user's local
 * repository using the currently configured version number.
 * 
 * @version Sep 23, 2013
 */
@Mojo( name = "latest-version", defaultPhase = LifecyclePhase.INSTALL )
public class InstallLatestVersionMojo extends AbstractMojo {

/**
 * Location of the .m2 directory
 */
@Parameter( defaultValue = "/${user.home}/.m2/repository", property = "outputDir", required = true )
private File repositoryLocation;

@Parameter( defaultValue = "${project.groupId}", property = "groupId", required = true )
private String groupId;

@Parameter( defaultValue = "${project.artifactId}", property = "artifactId", required = true )
private String artifactId;

/**
 * Version to use as the installed version
 */
@Parameter( defaultValue = "${project.version}", property = "version", required = true )
private String version;

public void execute() throws MojoExecutionException, MojoFailureException {
    try {
        // Fetch the xml file to edit from the user's repository for the project
        File installDirectory = getInstallDirectory(repositoryLocation, groupId, artifactId);
        File xmlFile = new File(installDirectory, "maven-metadata-local.xml");
        Document xml = getXmlDoc(xmlFile);

        if (xml != null) {
            // Fetch the <latest> node
            Node nodeLatest = getNode(xml, "/metadata/versioning/latest");
            if (nodeLatest == null) {
                // If <latest> does not yet exist, insert it into the <versioning> block before <versions>
                nodeLatest = xml.createElement("latest");
                Node versioningNode = getNode(xml, "/metadata/versioning");
                if (versioningNode != null) {
                    versioningNode.insertBefore(nodeLatest, getNode(xml, "metadata/versioning/versions"));
                }
            }
            // set the version on the <latest> node to the newly installed version
            nodeLatest.setTextContent(version);
            // save the xml
            save(xmlFile, xml);
        }

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

private void save(File xmlFile, Document xml) throws TransformerFactoryConfigurationError, TransformerException {
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    Result output = new StreamResult(xmlFile);
    Source input = new DOMSource(xml);
    transformer.transform(input, output);
}

private Node getNode(Document source, String path) throws XPathExpressionException{
    Node ret = null;
    XPathExpression xPath = getPath(path);
    NodeList nodes = (NodeList) xPath.evaluate(source, XPathConstants.NODESET);
    if(nodes.getLength() > 0 ) {
        ret = nodes.item(0);
    }
    return ret;
}

private XPathExpression getPath(String path) throws XPathExpressionException{
    XPath xpath = XPathFactory.newInstance().newXPath();
    return xpath.compile(path);
}

private File getInstallDirectory(File repositoryLocation, String groupId, String artifactId) {
    String group = groupId.replace('.', '/');
    return new File(repositoryLocation, group + "/" + artifactId);
}

private Document getXmlDoc(File xmlFile) throws ParserConfigurationException, SAXException, IOException {
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    return dBuilder.parse(xmlFile);
}

}
于 2013-09-25T18:26:29.643 回答
1

如果您正在使用 SNAPSHOT,则不需要版本范围,除了从不使用版本范围(仅在极少数情况下)。对于版本范围,您的构建是不可重现的,我认为在任何情况下都应该避免。

但是你可以使用这样的东西:

<version>[1.2.3,)</version

但是正如您已经意识到这会导致一些问题,但我建议使用versions-maven-plugin 作为替代方案来相应地更新项目pom 文件。

mvn clean versions:use-latest-versions scm:checkin deploy -Dmessage="update versions" -DperformRelease=true

这可以通过像 Jenkins 这样的 CI 解决方案来处理。但我的印象是你做错了一些基本的事情。特别是如果您需要使用版本范围。

于 2013-06-14T15:32:24.787 回答
0

如何将这些内部依赖项定义为一个反应堆 pom 中的模块?这样,您将针对已编译的源(在目标/类中)而不是针对 jar 进行编译,并且您将始终拥有最新的代码。

于 2013-06-15T13:17:57.893 回答