如何在安装工件时更新maven-metadata-local中的<latest>标签?</latest>

时间:2013-06-14 09:22:53

标签: maven

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

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

在本地安装工件时,有没有办法让maven-metadata-local.xml文件中的LATEST标记更新?

3 个答案:

答案 0 :(得分: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解决方案来处理。但我的印象是你做了一些基本的错误。特别是如果您需要使用版本范围。

答案 1 :(得分:1)

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

创建maven插件的文档位于The Apache Maven Project。您可以从命令行archetype创建一个插件项目,并将此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);
}

}

答案 2 :(得分:0)

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