Modifying an existing CopySpec


(Russ Egan) #1

I’ve run into a few cases now where I want to modify an existing CopySpec. Here’s an example:

I’m using the application plugin. I have a few additional scripts I want to bundle with my distZip, so I add them to src/dist/bin. But I also want to change the fileMode on those files.

The application plugin already includes everything from dist/**/* into the distZip. There’s no way for me to modify the applicationDistribution CopySpec to add the fileMode property to the files in the bin folder. If i just add

applicationDistribution.into('bin') {
   from file('src/dist/bin')
   fileMode 0755
}

…I get two copies of the bin files in the zip.

I’ve run into similar situations trying to add filters to an existing CopySpec.

eachFile() can be used to address some of these use cases. But it seems like most of these use cases could be expressed in a DSL very similar to what CopySpec already uses. I know there are ambiguity issues distinguishing between what are additional instructions and what are modifications to prior instructions, but doesn’t it seem intuitive that if I want to modify the output tree of a CopySpec to make all files in the ‘bin’ folder executable, I’d write something like:

spec {
  into('bin') {
    fileMode = 0755
  }
}

I’m not defining how inputs map to outputs here, I’m just expressing additional processing on the outputs. I wonder if that something like that could be supported. Like with a ‘transform’ method (or ‘postprocess’ or something), e.g.:

distSpec.with {
            from(project.file("src/dist"))
              into("lib") {
                from(jar)
                from(project.configurations.runtime)
            }
            into("bin") {
                from(startScripts)
                fileMode = 0755
            }
        }
}
  distSpec.transform('bin') {
    fileMode = 0755
    exclude = "*test"
}

I guess under the covers, that would apply fileMode and the exclude filter to all specs whose ‘into’ is bin.

Another approach might be chaining CopySpecs. E.g. cp2 { from cp1 } That is already supported, but it just adds cp1 to cp2 as a child. It doesn’t compute the final output tree of executing cp1, then use that as the input file tree for cp2, which is what you’d need to use cp2 to modify the output of cp1 (as opposed to just adding to it as it does now).


(andrew.oberstar) #2

Another option would be to add setFileMode/setDirMode to the FileCopyDetails interface. Then you could do something like this:

distSpec.eachFile {
  if (it.relativePath.segments[1] == 'bin') {
    it.fileMode = 0755
  }
}

(Russ Egan) #3

I don’t think fileMode is a property of FileCopyDetails. Just CopySpec.