2

I'm using this Gradle SSH plugin. It has a method put that will move files from my local machine to the machine the session is connected to.

My app is fully built and exists in build/app and I'm trying to move it to /opt/nginx/latest/html/ such that the file build/app/index.html would exist at /opt/nginx/latest/html/index.html and that any subfolders of build/app are also copied over.

My build.gradle:

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'org.hidetake:gradle-ssh-plugin:1.1.4'
  }
}

apply plugin: 'org.hidetake.ssh'

remotes {
  target {
    host = '<my target vm>'
    user = 'user'
    password = 'pass'
  }
}

...

task deploy() << {
  ssh.run {
    session(remotes.target) {
      put from: 'build/app/', into: '/opt/nginx/latest/html/'
    }
  }
}

As I have it above, it's putting all the files into /opt/nginx/latest/html/app. If I change the from to use fileTree(dir: 'build/app') then all the files get copied over but I lose the file structure, i.e. build/app/scripts/main.js gets copied to /opt/nginx/latest/html/main.js instead of the expected /opt/nginx/latest/html/scripts/main.js.

How can I copy the CONTENTS of one directory (not the directory itself) into the target directory while retaining folder structure?

Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188

3 Answers3

3

Looking through the plugin's code, it says:

    static usage = '''put() accepts following signatures:
        put(from: String or File, into: String)  // put a file or directory
        put(from: Iterable<File>, into: String) // put files or directories
        put(from: InputStream, into: String)     // put a stream into the remote file
        put(text: String, into: String)          // put a string into the remote file
        put(bytes: byte[], into: String)         // put a byte array into the remote file'''

You're using option #1 where you are providing a File (which can also be a directory), while you should be using #2, which would be an iterable list of build/app's children. So I would try:

put (from: new File('build/app').listFiles(), into: '/opt/nginx/latest/html/')

Edit: Alternatively,

new File('build/app').listFiles().each{put (from:it, into:'/opt/nginx/latest/html/')}
RaGe
  • 22,696
  • 11
  • 72
  • 104
  • `File` seems ambiguous. If I write what you have then I get `No signature of method: org.hidetake.groovy.ssh.session.SessionHandler.File() is applicable for argument types`. Changing it to `new File(...)` or `file(...)` doesn't work either. I also have to wrap quotes around `build/app` as well. – Corey Ogburn Jan 12 '16 at 21:48
  • Sorry, just typed that in while commuting. Should say new File, wrap in quotes, also should probably assemble the list of files separately and then use it here. I'll have a chance to test this in maybe an hour. – RaGe Jan 12 '16 at 22:35
  • I get the error `No signature of method: org.hidetake.groovy.ssh.session.SessionHandler.put() is applicable for argument types: ([java.io.File, java.lang.String) values: [[build\app\index.html, build\app\scripts, build\app\styles, ...], ...]` – Corey Ogburn Jan 13 '16 at 15:43
  • That's weird, the error message has an opening `[` in `([java.io.File, java.lang.String)` but not closing? Anway, adding an alternate way. – RaGe Jan 13 '16 at 17:12
  • That may be my command prompt misinterpreting colors. I use cmder and it's not always perfect about things like that. – Corey Ogburn Jan 13 '16 at 17:13
  • In the first option a little change is needed to make it a Collection as File[] is not fitting here somehow in groovy, call collect() on listFiles() like new File('build/app').listFiles().collect() – SandeepGodara Oct 25 '16 at 12:52
2

You could create a FileTree object for your build/app directory and then ssh your entire tree structure to your remote instance:

FileTree myFileTree = fileTree(dir: 'build/app')

task deploy() << {
  ssh.run {
    session(remotes.target) {
      put from: myFileTree.getDir(), into: '/opt/nginx/latest/html/'
    }
  }

It should copy your structure and files like:

// 'build/app'         -> '/opt/nginx/latest/html/
// 'build/app/scripts' -> '/opt/nginx/latest/html/scripts/'
// 'build/app/*.*'     -> 'opt/nginx/latest/html/*.*'
// ...
destepp11
  • 53
  • 8
0

You could add a wildcard to copy all files in the folder:

put from: 'build/app/*', into: '/opt/nginx/latest/html/'
Alla B
  • 656
  • 3
  • 9
  • When I do this, I get `java.io.FileNotFoundException: C:\my\absolute\path\build\app\scripts (Access is denied)`. I'm not sure exactly what it's trying to do here because that folder definitely exists. I think it's trying to access that folder as a file. It does successfully move over files in the root of `build/app` but not any of the folders or files in those sub folders. – Corey Ogburn Jan 12 '16 at 20:36
  • @CoreyOgburn Sorry, didn't ask what OS you had and assumed *NIX. – Alla B Jan 12 '16 at 21:50
  • It needs to be OS agnostic. Our team has mac and windows machines all accessing the same repo and using this build.gradle. – Corey Ogburn Jan 12 '16 at 21:54