Groovy directory diff

A Java verziókban hanyagoltam a legalapabb megoldást: directory pollozó implementációt. Egyszerűen azért, mert Java nem egy barátságos nyelv és az IO API különösen nem az. (Miért? Mert nem szeretem a checked Exception-öket.).

Groovy/ viszont más. Abban lehet elegánsan is programozni. A következő példa nem is directory watch, csak egy példa implementáció arra, hogyan lehet beazonosítani a változásokat. A kulcsa a mapDiff függvény.

NB: Ezt a scriptet használom a site feltöltésére, mert nem akarok mindent feltölteni, csak a változott tartalmakat.

  1@GrabConfig(systemClassLoader=true)
  2@Grapes([
  3@Grab(group='ant', module='ant', version='1.7.0'),
  4@Grab(group='ant', module='ant-nodeps', version='1.6.5'),
  5@Grab(group='ant', module='ant-apache-oro', version='1.6.5'),
  6@Grab(group='ant', module='optional', version='1.5.4'),
  7@Grab(group='commons-net', module='commons-net', version='1.4.1'),
  8@Grab(group='commons-io', module='commons-io', version='2.4'),
  9@Grab(group='ant', module='ant-jakarta-oro', version='1.6.1'),
 10@Grab(group='ant', module='ant-commons-net', version='1.6.5')
 11])
 12
 13
 14import org.apache.commons.net.ftp.FTPClient
 15import org.apache.commons.io.*
 16import groovy.io.FileType
 17import java.security.MessageDigest
 18import groovy.json.JsonBuilder
 19import groovy.json.JsonSlurper
 20
 21ftp_host="xxx"
 22ftp_user="xxx"
 23ftp_pass="xxx"
 24ftp_dir='xxx'
 25
 26scriptDir = new File(getClass().protectionDomain.codeSource.location.path).parent
 27checksumFile = new File(scriptDir, "../tmp/gchecksum.json")
 28base_dir = new File(scriptDir, "../output")
 29println base_dir
 30
 31def main(){
 32        def currentHash = generateHash()
 33        if(!checksumFile.exists()){
 34                upload(currentHash, [:])
 35                writeChecksum(currentHash)
 36                return
 37        }
 38        println 'Comparing...'
 39        println 'Reading previous hash...'
 40        def preHash = readHash()
 41        def diff = mapDiff(preHash, currentHash)
 42        println 'Removed'
 43        println diff.removed
 44        println 'Changed'
 45        def changed = [:]
 46        changed.putAll(diff.added)
 47        changed.putAll(diff.changed)
 48        println changed
 49        upload(changed, diff.removed)
 50        writeChecksum(currentHash)
 51}
 52
 53def generateHash(){
 54        println 'Generating current hash...'
 55        Map hashes = [:]
 56        allFiles(base_dir).each{ File file ->
 57                def md = generateMD5(file)
 58                hashes[file.path.substring(base_dir.path.length()+1)]=md
 59        }
 60        println "${hashes.size()} hashes are generate."
 61        hashes
 62}
 63
 64def allFiles(File dir){
 65        def list = []
 66        dir.eachFileRecurse (FileType.FILES) { file ->
 67          list << file
 68        }
 69        list
 70}
 71
 72def generateMD5(final file) {
 73       MessageDigest digest = MessageDigest.getInstance("MD5")
 74       file.withInputStream(){is->
 75       byte[] buffer = new byte[8192]
 76       int read = 0
 77          while( (read = is.read(buffer)) > 0) {
 78                 digest.update(buffer, 0, read);
 79             }
 80         }
 81       byte[] md5sum = digest.digest()
 82       BigInteger bigInt = new BigInteger(1, md5sum)
 83       return bigInt.toString(16).padLeft(32, '0')
 84}
 85
 86def toJson(m){
 87        builder = new JsonBuilder()
 88        builder(m)
 89        builder.toString()
 90}
 91
 92def writeChecksum(m){
 93        checksumFile.text=toJson(m)
 94}
 95
 96def readHash(){
 97        slurper = new JsonSlurper()
 98        slurper.parseText(checksumFile.text) 
 99}
100
101def mapDiff(Map oldMap, Map newMap){
102        def newKeys = newMap*.key
103        def oldKeys = oldMap*.key
104         
105        def removedKeys = oldKeys-newKeys
106        def addedKeys = newKeys - oldKeys
107        def commonKeys =newKeys - removedKeys - addedKeys
108        def changedKeys = commonKeys.findAll { oldMap[it] != newMap[it] }
109        def unchangedKeys = commonKeys - changedKeys
110         
111        def changes = [
112        removed: oldMap.findAll { it.key in removedKeys },
113        added: newMap.findAll { it.key in addedKeys },
114        changed: oldMap.findAll { it.key in changedKeys },
115        unchanged: newMap.findAll { it.key in unchangedKeys }
116        ]
117}
118
119
120def upload(uploadable, deletable){
121        def ant = new AntBuilder()
122        if(uploadable.size() != 0){
123                ant.ftp(server: ftp_host, 
124                                userid: ftp_user, 
125                                password: ftp_pass, 
126                                remotedir: ftp_dir, 
127                                passive:"yes",
128                                verbose: "yes",
129                                binary:"yes",
130                                action: "put"){
131                        fileset(dir:base_dir.path){
132                                uploadable.each{
133                                        include(name:it.key)
134                                }
135                        }
136                }
137        }
138        if(deletable.size() == 0){
139                return
140        }
141        ant.ftp(server: ftp_host, 
142                        userid: ftp_user, 
143                        password: ftp_pass, 
144                        remotedir: ftp_dir, 
145                        passive:"yes",
146                        verbose: "yes",
147                        binary:"yes",
148                        action: "delete"){
149                fileset(dir:base_dir.path){
150                        deletable.each{
151                                include(name:it.key)
152                        }
153                }
154        }
155}
156
157main()

Directory Watcher
Sep 22, 2013
comments powered by Disqus

Links

Cool

RSS