How do I apply a patch file in Gradle?

荒凉一梦 提交于 2019-12-05 12:43:30

You should be able to translate your ant call into gradle pretty directly.

The gradle doc on how to do this generically. Basically attributes become named arguments and child tags become closures. The documentation has a bunch of good examples.

Once you have your translated ant task you can put in in a doFirst or doLast block on an appropriate task.

My first guess would be something like this:

apply plugin: 'java'

assemble.doFirst {
    ant.patch(patchfile: applicationContext.patch.file,
              originalFile: "${dist.dir}/applicationContext.xml")
}

That's untested, so but I'm pretty sure it will get you started on the right path. The intent is that just before the java plugin assembles your archive you want gradle to call a closure. In this case the closure will perform an ant action that patches your xml.

Alternately you could use the task you have above that performs a copy and tag onto that.

task myCopyTask(type: Copy) {
    ...
} << {
    ant.patch(patchfile: applicationContext.patch.file,
              originalFile: "${dist.dir}/applicationContext.xml")
}

In this case you are writing the task yourself and the left-shift operator (<<) is equivalent to .doLast but a whole lot cooler. I'm not sure which method you prefer, but if you already have a copy task that gets the file there in the first place, I think doLast keeps the relevant code blocks as close to each other as possible.

If you'd like to do this more on the fly I can think of two main techniques. Both involve writing some code, but they may be more appealing to you and I'm pretty confident gradle doesn't have this behavior built-in anywhere.

Personally I think #1 is the better solution, since you don't need to muck around with the internals of the Copy task. A custom filter feels cleaner and more reusable.

1) Write a custom filter that you specify in your copy task. I can't help with the details of how to write a custom filter, but I'd start here. You should be able to put the custom filter in buildSrc (lots of info about that at gradle.org) and then you simply need to import it at the top of your gradle file. If you write it in groovy I think you can even just use ant.patch() again.

task copyAndPatch() {
    into('META-INF') {
    from 'deployment', {
        include 'applicationContext.xml'
        rename { fn -> "jboss-spring.xml' }
        filter(MyCustomFilterThatDoesAPatch, patchFile: 'local/applicationContext.xml.patch')
    }
}

2) Write a custom task. Again, I'll leave the details to the experts but you can probably get away with subclassing the Copy task, adding a 'patch' property, and then jumping in during execution to do the dirty work.

RFC 5621 defines an XML patching language that uses XPath to target the location in the document to patch. It's great for tweaking config files.

There is an open source implementation in Java (Disclaimer: I am the author). It includes a filter that can be used from Gradle to patch XML files during any task that implements CopySpec. For example:

buildscript {
    repositories { jcenter() }
    dependencies { classpath "com.github.dnault:xml-patch:0.3.0" }
}

import com.github.dnault.xmlpatch.filter.XmlPatch

task copyAndPatch(type: Copy) {
    // Patch file in RFC 5621 format
    def patchPath = 'local/applicationContext-patch.xml'

    inputs.file patchPath

    into('META-INF') {
        from 'deployment', {
            include 'applicationContext.xml'
            rename { 'jboss-spring.xml' }
            filter(XmlPatch, patch: patchPath)
        }
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!