From 1b64a93dc7c5642ebd7989ae28b9a91f1f07f577 Mon Sep 17 00:00:00 2001 From: Ivan Olexyn Date: Sat, 18 Jan 2020 12:00:02 +0100 Subject: [PATCH] List of changes: * Remove the config file. Directories are now registered to SyncEntity and syncronized. * Thus any number of directories can be synced. * Supports 3 out of 10 file operations. See png diagram. * Mainly sync operations that require modification times are not present yet. --- README.md | 6 +- src/com/olexyn/ensync/Core.java | 13 + src/com/olexyn/ensync/Main.java | 103 ++- src/com/olexyn/ensync/Tools.java | 94 ++- .../ensync/artifacts/SyncDirectory.java | 134 ++++ .../olexyn/ensync/artifacts/SyncEntity.java | 86 +++ .../ensync/file-ops-covered-vs-missing.png | Bin 0 -> 26195 bytes .../ensync/file-ops-covered-vs-missing.uxf | 458 ++++++++++++++ src/com/olexyn/ensync/handle-deletes.png | Bin 0 -> 27909 bytes src/com/olexyn/ensync/handle-deletes.uxf | 588 ++++++++++++++++++ src/com/olexyn/ensync/shell/pipe.sh | 6 + src/com/olexyn/ensync/shell/pipe2.sh | 7 + src/com/olexyn/ensync/shell/toFile.sh | 7 + src/com/olexyn/ensync/sync.conf | 13 - 14 files changed, 1487 insertions(+), 28 deletions(-) create mode 100644 src/com/olexyn/ensync/Core.java create mode 100644 src/com/olexyn/ensync/artifacts/SyncDirectory.java create mode 100644 src/com/olexyn/ensync/artifacts/SyncEntity.java create mode 100644 src/com/olexyn/ensync/file-ops-covered-vs-missing.png create mode 100644 src/com/olexyn/ensync/file-ops-covered-vs-missing.uxf create mode 100644 src/com/olexyn/ensync/handle-deletes.png create mode 100644 src/com/olexyn/ensync/handle-deletes.uxf create mode 100755 src/com/olexyn/ensync/shell/pipe.sh create mode 100755 src/com/olexyn/ensync/shell/pipe2.sh create mode 100755 src/com/olexyn/ensync/shell/toFile.sh delete mode 100644 src/com/olexyn/ensync/sync.conf diff --git a/README.md b/README.md index 21287b7..78089d8 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Sync files across directories: | Class | Description | |---------------|-------------| -| Execute | Issues shell commands.| +| Execute | Issues com.olexyn.ensync.shell commands.| | Main | Main class. Run from here.| | Routines | Contains higher level routines.| | Tools | Simple tools used by other classes.| @@ -30,4 +30,6 @@ Sync files across directories: ### Issues - What about parallel Threads? -- What about error handling? (i.e. if a web-directory is not available) \ No newline at end of file +- What about error handling? (i.e. if a web-directory is not available) +- Make commands more expressive e.g. collection dir dir dir -> keep all 3 dirs on sync. +- Figure out a way to handle deletions. \ No newline at end of file diff --git a/src/com/olexyn/ensync/Core.java b/src/com/olexyn/ensync/Core.java new file mode 100644 index 0000000..3ec0003 --- /dev/null +++ b/src/com/olexyn/ensync/Core.java @@ -0,0 +1,13 @@ +package com.olexyn.ensync; + +import java.util.List; + +public class Core { + + + public Core(){ + + } + + +} diff --git a/src/com/olexyn/ensync/Main.java b/src/com/olexyn/ensync/Main.java index 56cfa50..32fff86 100644 --- a/src/com/olexyn/ensync/Main.java +++ b/src/com/olexyn/ensync/Main.java @@ -1,24 +1,109 @@ package com.olexyn.ensync; -import java.io.BufferedReader; -import java.util.ArrayList; -import java.util.List; +import com.olexyn.ensync.artifacts.SyncDirectory; +import com.olexyn.ensync.artifacts.SyncEntity; -public class Main { +import java.io.File; +import java.util.*; +public class Main { public static void main(String[] args) { - String conf = new Tools().getConf(); - List cmdBuffer = new Routines().parseConfToCmdBuffer(conf); + Tools tools = new Tools(); + Execute x = new Execute(); + + + SyncEntity syncEntity = new SyncEntity("test"); + syncEntity.addDirectory("/home/user/test/a"); + syncEntity.addDirectory("/home/user/test/b"); + syncEntity.addDirectory("/home/user/test/c"); + + int br1 = 0; + + while (true) { + + for (Map.Entry entry : syncEntity.syncDirectories.entrySet()) { + + SyncDirectory syncDirectory = entry.getValue(); + + + syncDirectory.updateStateFileNew(); + syncDirectory.updatePoolNew(); + + // + for (File createdFile : syncDirectory.getListCreated()) { + for (Map.Entry otherEntry : syncEntity.syncDirectories.entrySet()) { + SyncDirectory otherSyncDirectory = otherEntry.getValue(); + + if (!syncDirectory.equals(otherSyncDirectory)){ + // Example: + // syncDirectory /foo + // otherSyncDirectory /bar + // createdFile /foo/hello/created-file.gif + // relativePath /hello/created-file.gif + String relativePath = createdFile.getPath().replace(syncDirectory.realPath, ""); + String targetPath = otherSyncDirectory.realPath + relativePath; + String targetParentPath = new File(targetPath).getParent(); + if (!new File(targetParentPath).exists()){ + String[] cmd = new String[]{"mkdir", + "-p", + targetParentPath}; + x.execute(cmd); + } + + String[] cmd = new String[]{"cp", + createdFile.getPath(), + otherSyncDirectory.realPath + relativePath}; + x.execute(cmd); + } + } + + } + + // + for (File deletedFile : syncDirectory.getListDeleted()) { + + for (Map.Entry otherEntry : syncEntity.syncDirectories.entrySet()) { + SyncDirectory otherSyncDirectory = otherEntry.getValue(); + + if (!syncDirectory.equals(otherSyncDirectory)){ + String relativePath = deletedFile.getPath().replace(syncDirectory.realPath, ""); + String[] cmd = new String[]{"rm", "-r", + otherSyncDirectory.realPath + relativePath}; + x.execute(cmd); + } + } + + } + + + syncEntity.addToMapCreated(syncDirectory.getListCreated()); + syncEntity.addToMapDeleted(syncDirectory.getListDeleted()); +// + // WARNING: + // Be very carefull when to update the StateFileOld + // i.e. you create a File and update StateFileOld without updating + // -> create newFile -> update StateFileNew-> getListCreated contains newFile -> addToMapCreated -> create copies as needed -> updateStateFileOld -> OK + // -> create newFile -> update StateFileOld -> getListDeletd contains newFile -> VERY BAD + // + syncDirectory.updateStateFileBoth(); + syncDirectory.updatePoolBoth(); + + - System.out.println("bar"); - new Execute().executeBatch(cmdBuffer); + } + //Map mapCreated = syncEntity.getMapCreated(); + //Map mapDeleted = syncEntity.getMapDeleted(); - String br = null; + int br = 0; + try {Thread.sleep(1000);} + catch (InterruptedException e){ + } + } } } diff --git a/src/com/olexyn/ensync/Tools.java b/src/com/olexyn/ensync/Tools.java index c77b774..e7ea453 100644 --- a/src/com/olexyn/ensync/Tools.java +++ b/src/com/olexyn/ensync/Tools.java @@ -1,7 +1,11 @@ package com.olexyn.ensync; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -15,14 +19,21 @@ public class Tools { /** + * */ - public void rsync(String param , String source , String destination) { + public void rsync(String param, + String source, + String destination) { // - BufferedReader foo = x.execute(new String[]{"rsync", param, source, destination}).output; + BufferedReader foo = x.execute(new String[]{"rsync", + param, + source, + destination}).output; } - public String getConf(){ - BufferedReader output = x.execute(new String[]{"cat", System.getProperty("user.dir")+"/src/com/olexyn/ensync/sync.conf"}).output; + public String getConf() { + BufferedReader output = x.execute(new String[]{"cat", + System.getProperty("user.dir") + "/src/com/olexyn/ensync/sync.conf"}).output; return brToString(output); } @@ -34,4 +45,79 @@ public class Tools { } return sb.toString(); } + + /** + * StateFile -> FilePool + */ + public Map fileToPool(File file, + String type) { + List lines = fileToLines(file); + return linesToFilePool(lines, type); + } + + + /** + * CREATE a StateFile from realPath.

+ * WRITE the StateFle to stateFilePath. + * @param realPath the path of the directory the StateFile is created for. + * @param stateFilePath the desired path for the created Statefile. + */ + public File generateStateFile(String realPath, String stateFilePath) { + String[] cmd = new String[]{System.getProperty("user.dir") + "/src/com/olexyn/ensync/shell/toFile.sh", + "find", + realPath, + stateFilePath}; + x.execute(cmd); + return new File(realPath); + } + + + public List fileToLines(File file) { + String filePath = file.getPath(); + List lines = null; + try { + lines = Files.readAllLines(Paths.get(filePath)); + } catch (IOException e) { + e.printStackTrace(); + } + return lines; + } + + + public Map linesToFilePool(List lines, + String type) { + + Map filepool = new HashMap<>(); + + for (String line : lines) { + File file = new File(line); + + if (type.equals("all") || type.equals("dir") && file.isDirectory() || type.equals("file") && file.isFile()) { + filepool.put(line, file); + } + } + return filepool; + } + + + public List mapMinus(Map fromA, + Map substractB) { + + List difference = new ArrayList<>(); + Iterator iterator = fromA.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator.next(); + String key = (String) entry.getKey(); + + File file = fromA.get(key); + + + if (fromA.containsKey(key) && !substractB.containsKey(key)) { + difference.add(file); + } + + + } + return difference; + } } diff --git a/src/com/olexyn/ensync/artifacts/SyncDirectory.java b/src/com/olexyn/ensync/artifacts/SyncDirectory.java new file mode 100644 index 0000000..8967730 --- /dev/null +++ b/src/com/olexyn/ensync/artifacts/SyncDirectory.java @@ -0,0 +1,134 @@ +package com.olexyn.ensync.artifacts; + +import com.olexyn.ensync.Tools; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SyncDirectory { + + public String realPath; + public String stateFileBasePath; + public String stateFileOldPath; + public String stateFileNewPath; + public File stateFileOld; + public File stateFileNew; + private Map poolOld = new HashMap<>(); + private Map poolNew = new HashMap<>(); + private List listCreated = new ArrayList<>(); + private List listDeleted = new ArrayList<>(); + + + Tools tools = new Tools(); + + /** + * Create a SyncDirectory from realPath. + * + * @param realPath + * @see SyncEntity + */ + public SyncDirectory(String realPath) { + this.realPath = realPath; + stateFileBasePath = "/tmp/find" + this.realPath.replace("/", "-"); + stateFileOldPath = stateFileBasePath + "-old"; + stateFileNewPath = stateFileBasePath + "-new"; + stateFileOld = getStateFileOld(); + stateFileNew = getStateFileNew(); + poolOld = getPoolOld(); + poolNew = getPoolNew(); + + } + + /** + * IF NOT EXISTS the StateFileOld for this SyncDirectory,

+ * - THEN create the File on Disk. + * + * @return the StateFileOld. + */ + public File getStateFileOld() { + stateFileOld = new File(stateFileOldPath); + if (!stateFileOld.exists()) { + stateFileOld = tools.generateStateFile(realPath, stateFileOldPath); + } + return stateFileOld; + } + + /** + * READ directory contents.

+ * WRITE a new StateFileNew to Disk. This is IMPORTANT in order to make sure that StateFileOld is NEVER newer than StateFileNew.

+ * WRITE a new StateFileOld to Disk. + */ + public void updateStateFileBoth() { + // + tools.generateStateFile(realPath, stateFileNewPath); + tools.generateStateFile(realPath, stateFileOldPath); + } + + public File getStateFileNew() { + stateFileNew = new File(stateFileNewPath); + if (!stateFileNew.exists()) { + stateFileNew = tools.generateStateFile(realPath, stateFileNewPath); + } + return stateFileNew; + } + + /** + * READ directory contents.

+ * WRITE a new StateFileNew Disk. + */ + public void updateStateFileNew() { + // + tools.generateStateFile(realPath, stateFileNewPath); + } + + + public Map getPoolOld() { + if (poolOld.isEmpty()) { + updatePoolBoth(); + } + return poolOld; + } + + /** + * UPDATE PoolOld FROM contents of StateFileOld. + */ + public void updatePoolBoth() { + poolNew = tools.fileToPool(getStateFileNew(), "all"); + poolOld = tools.fileToPool(getStateFileOld(), "all"); + + } + + + public Map getPoolNew() { + if (poolNew.isEmpty()) { + updatePoolNew(); + } + return poolNew; + } + + /** + * UPDATE PoolNew FROM contents of StateFileNew. + */ + public void updatePoolNew() { + poolNew = tools.fileToPool(getStateFileNew(), "all"); + + } + + public List getListCreated() { + + listCreated = tools.mapMinus(getPoolNew(), getPoolOld()); + + return listCreated; + } + + public List getListDeleted() { + + listDeleted = tools.mapMinus(getPoolOld(), getPoolNew()); + + return listDeleted; + } + +} diff --git a/src/com/olexyn/ensync/artifacts/SyncEntity.java b/src/com/olexyn/ensync/artifacts/SyncEntity.java new file mode 100644 index 0000000..16f2c6b --- /dev/null +++ b/src/com/olexyn/ensync/artifacts/SyncEntity.java @@ -0,0 +1,86 @@ +package com.olexyn.ensync.artifacts; + + +import com.olexyn.ensync.Tools; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A SyncEntity is a collection of SyncDirectories, + * that are supposed to be kept in sync. + */ +public class SyncEntity { + + public String name; + public int syncInterval = 3600; + public Map syncDirectories = new HashMap<>(); + private Map mapCreated = new HashMap<>(); + private Map mapDeleted = new HashMap<>(); + Tools tools = new Tools(); + + /** + * @see SyncEntity + */ + public SyncEntity(String name) { + this.name = name; + + } + + /** + * Creates a new Syncdirectory. + *

+ * Adds the created SyncDirectory to this SyncEntity. + * + * @param realPath the path from which the Syncdirectory is created. + * @see SyncDirectory + */ + public void addDirectory(String realPath) { + if (new File(realPath).isDirectory()) { + syncDirectories.put(realPath, new SyncDirectory(realPath)); + } + } + + public Map getMapCreated() { + for (Map.Entry entry : syncDirectories.entrySet()) { + SyncDirectory syncDirectory = entry.getValue(); + for (File file : syncDirectory.getListCreated()) { + mapCreated.put(file.getPath(), file); + } + + } + + + return mapCreated; + } + + public Map getMapDeleted() { + + for (Map.Entry entry : syncDirectories.entrySet()) { + SyncDirectory syncDirectory = entry.getValue(); + for (File file : syncDirectory.getListDeleted()) { + mapDeleted.put(file.getPath(), file); + } + + } + + + return mapDeleted; + } + + public void addToMapCreated(List listCreated) { + for (File file : listCreated) { + mapCreated.put(file.getPath(), file); + } + } + + + public void addToMapDeleted(List listDeleted) { + for (File file : listDeleted) { + mapDeleted.put(file.getPath(), file); + } + } + +} diff --git a/src/com/olexyn/ensync/file-ops-covered-vs-missing.png b/src/com/olexyn/ensync/file-ops-covered-vs-missing.png new file mode 100644 index 0000000000000000000000000000000000000000..c6ed079de83b4065d96284f96ed18410e18e0e8d GIT binary patch literal 26195 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 literal 0 HcmV?d00001 diff --git a/src/com/olexyn/ensync/file-ops-covered-vs-missing.uxf b/src/com/olexyn/ensync/file-ops-covered-vs-missing.uxf new file mode 100644 index 0000000..29b776f --- /dev/null +++ b/src/com/olexyn/ensync/file-ops-covered-vs-missing.uxf @@ -0,0 +1,458 @@ + + + 10 + + UMLObject + + 290 + 420 + 110 + 40 + + Directory B + + + + UMLObject + + 290 + 380 + 110 + 40 + + Directory A + + + + UMLObject + + 290 + 230 + 110 + 40 + + Delete +bg=red +group=1 + + + + UMLObject + + 290 + 270 + 110 + 40 + + Create +bg=green +group=1 + + + + UMLObject + + 290 + 310 + 110 + 40 + + Modify +bg=yellow +group=1 + + + + UMLState + + 440 + 530 + 70 + 40 + + YES +bg=green + + + + UMLState + + 440 + 420 + 70 + 40 + + File + + + + UMLState + + 530 + 420 + 70 + 40 + + File +bg=red + + + + UMLState + + 890 + 530 + 70 + 40 + + NO +bg=red + + + + UMLObject + + 290 + 190 + 110 + 40 + + Unchanged +bg=white +group=1 + + + + UMLState + + 440 + 380 + 70 + 40 + + File + + + + UMLState + + 530 + 380 + 70 + 40 + + File + + + + UMLState + + 620 + 420 + 70 + 40 + + File +bg=red + + + + UMLState + + 620 + 380 + 70 + 40 + + File +bg=red + + + + UMLState + + 710 + 420 + 70 + 40 + + File +bg=green + + + + UMLState + + 710 + 380 + 70 + 40 + + File + + + + UMLState + + 800 + 420 + 70 + 40 + + File +bg=green + + + + UMLState + + 800 + 380 + 70 + 40 + + File +bg=green + + + + UMLState + + 890 + 420 + 70 + 40 + + File +bg=yellow + + + + UMLState + + 890 + 380 + 70 + 40 + + File + + + + UMLState + + 980 + 420 + 70 + 40 + + File +bg=yellow + + + + UMLState + + 980 + 380 + 70 + 40 + + File +bg=yellow + + + + UMLState + + 1070 + 380 + 70 + 40 + + File +bg=red + + + + UMLState + + 1070 + 420 + 70 + 40 + + File +bg=green + + + + UMLState + + 1160 + 380 + 70 + 40 + + File +bg=red + + + + UMLState + + 1160 + 420 + 70 + 40 + + File +bg=yellow + + + + UMLState + + 1250 + 380 + 70 + 40 + + File +bg=green + + + + UMLState + + 1250 + 420 + 70 + 40 + + File +bg=yellow + + + + UMLNote + + 420 + 190 + 150 + 80 + + 2^4 = 16 +however only 10 +because 6 are symmetrical. +bg=white + + + + UMLObject + + 290 + 530 + 110 + 40 + + Covered? + + + + UMLState + + 620 + 530 + 70 + 40 + + MAYBE +bg=yellow + + + + UMLState + + 530 + 530 + 70 + 40 + + YES +bg=green + + + + UMLState + + 710 + 530 + 70 + 40 + + YES +bg=green + + + + UMLState + + 980 + 530 + 70 + 40 + + NO +bg=red + + + + UMLState + + 1160 + 530 + 70 + 40 + + NO +bg=red + + + + UMLState + + 1250 + 530 + 70 + 40 + + NO +bg=red + + + + UMLState + + 800 + 530 + 70 + 40 + + NO +bg=red + + + + UMLState + + 1070 + 530 + 70 + 40 + + NO +bg=red + + + diff --git a/src/com/olexyn/ensync/handle-deletes.png b/src/com/olexyn/ensync/handle-deletes.png new file mode 100644 index 0000000000000000000000000000000000000000..4bc2151d4231c312c71dc8001abaf1b898f901b1 GIT binary patch literal 27909 zcmdSBby$?$+b#?kz#yTN(ui~l0@9_RAT8Y@T|*8H(ujb9lt>5yij+zWtpkEI3X($% z9WqEs!?%VJpXc|!?{|Fr`(q#b*#E&j_qtbIYpv@#&+}T*8fr?!5E=*$4i53%JGZoO zaBw$qaPaB~@W7K~y%9Ma9LLVPx8&}7oBkXly?@{8NamO3t&5b}ik~i~$&yo#X?&ph zs7uObZ5}Wv^M+FF$lx&VT_wawh3#;dXP{kJz`;m&uo5BJ%In5!BvO^AX{gu=o(sf| z1hLaCV?Y+S^j_9pP`B(0#cP-ObOY$ax4!c+g?4oO80{ChP+oQ9SsNK)&H-D6~k-m z9sJu%KVmrV-Mja*&bp`4b6GbZg7>=e5mP6o0#`4`;Sb>|_TxFXV|EPNpz{~52wwXI zl?m9}d?D^;bSc2j}_nVXZ7 zDj#%~6-fkv81oG(F$VO1|GvJrT-x(OIL1VQI7~vH9(3Z8O{6h=b+js;_Uk*EY8NE@ zy0CBsY<1kgz@W5Yk4wA5*2N`0Hg>GSf!YYQ5wP}!daM>!`t~hKWnu7Btmyb1QgLzd z$1yRB3x|7K9bH|AGl}YNe$BKc$^`z}A+(Zetlo+KM)V{;K1hiO|mAoO)9+;T&hEfzI*p>kJL8Z z@yhGFi36o({BKgqoJK`Pf|Qlp4|X?TKZjh=NU?^cG@Hy~!^72}g4RK^pu_dqj_UPz znIrGsY`Jo_*x_yT*y#9p_o}iWayIjFxJ3O~LyP(DjI^}0&B?a~nKgS$@4`nTGXGV% zC~_ije;a6fv{_2?o_DpYi{e;xiorTAdG5nR~<#b|h4}TQu`2GHQ(UI9=t~0HiB(_UEL;UtGEj@j} z&MylTq$!fL0D;fw|CFDTmzS5H-^JE;=l7@!HIKdku(;1l4WC2tCp-sDki$NiGykge zYxsVWo~d2!Qvr*+0Rd9CE#euZ97AGA82x^}zsRDv`Eyu^g(Vd6g3#bPjTJDmG3Tn* zFJEFAWdgy#cS5!&f`Y&w>Mw78PPri>!e`ciL_s%KCxVvx-+Fp_hWrSq^;)43alBlA z74>obuGIA~iBvMM@;(@QQBYB-WlE;;5}PGEFcI(pYkXMz^QQ0S!fk4ka?4hd%B%hc z?;bHNVAgc_htTssuV24jHRhE*!>fjBmnS~!E4vY@_?0A4;mqxupm5kv0kInzVG92j zJ^Z_|;(`^t8U)PkA|>V4uuax`Pn>};Xk?V)`=j)U1M5%0xSO5^>|Vq;4)Sn?uuCoC zQuzsUbJn$EreU357S204xI*fN%z&6_=^zT)KQQot5+^wX8d;VnGT>unW#!}J zE19=HT$IZ?Wj@TMKTSqBAHG3)WBi^E&tMKeVy=n1?g)2pTDHu}FWu zyrLqnpg>Pg?;|A+)gvf=2a$8p1{XKC2_Ll)#QY)wtV|%|K}O%VZ_m=w40Lq9=;G+( zBItSU4(iWqe$Z~vZU^P^Bcb>)gsMdw#(a8U8wBNiLAfVnt>OhWHR4iI^~J@p#W(_@ zU>gr+e&5~E-CgqLjkyYLCozg7-`cUr-QM2*rJ9X{1Gf>b`2zx&0H;v1I6pssX;IM= z-g5#NBaD0dAVb^8Xc>C5&Xga#r3>D=NZumOFC)`fUj7`s#SPvHNwdt**3(OQ`gC&5 zdkBJ~Ee{X<+{w5sSv6{+rG-ewOTC1kzhL=Ff4+ZkaCGH2n3PJqPyS?RbDWMZ;x5A< ztZv`F4aRU6jN$7d+U1uK5fM8(-h1u3IH?y9^zzM1@4IuKNyJWo*+`UwhoTW|17clW zU0${I4Go!~i{xPv3mlyfGW5X7=T!^d5(01WA%q9S7~B#q&Ru<^y`!VnA&?d zC=#06ZeY&1xITRR2&yEPg@@Wld72s-8TtD9dU^_j;kpqf@g`WG`dv|xN3}8N;5Rb# zBz1Gm%ec6>&d$!lLM~9B1_5jV??JuF^PkUGpRYTf3w9+#GZDQ<%cOMZ7#OrA<6Xu_ zkz68Mw%5_qD<~+as;B@~dR`9RbdGHKg_Vts-u?S!c_$B!nFh|>*Vdl)5C?4-hTyO; zA#vX`+yM3otQ6FKkqmv2_&tMhMMVWkWYh8%uw&*(XuL+0XU5F@d`fcihrE*qH={gF ze*E~sdhMFGBts=0Q#mMi_B{iQb5-r@*I~Tp2zbN%Zpju!Y6S$;k2$+IJ6m(($P=I# z=E#;K^eY_=G&L_8LCE9@w#&lxMKu%@6#V@q1FXP1=THn0WXsmFEHIizuozy2KuNiy zJU48eohwIIwzjq$&&l3lLN=X!Fczk)tc-LP1)sS@0P9dFN>6T`zI*4+n|JRlxp6il zp;ZFSHM>d4$#e7b;6r-~aHC5P#<=QCOPf${ii<&A9ud&0%gr^j&y$kC(fU3QM;yF! z{=ry|p^;IBnvJR|u@P=Idsyu`rh(#;oSdr?66w6>ddU%E{bb9iSH;D=VENS4yeP)$ zB}R#)fcHR3 z9&TLH-mY9pA&XA{3uPW)Q3ks`unus(8R3#S62O|623WMcyu5DTJ_q^=9-ILW3{+KP z`xYIYoIpQ9ASi}6LN?uHx7W#*W!Kl&+uPfRw1Ttc;rKH{?=5dYHhk+H!wDYHdt+xc zi;)(miwuq1*48#$W^u;Im$_LyYW8$?KZimGo%esQ0M8AgC(SeJ#$Ev@gb6e5Qnt3`P(B#f@`adKLy;GX;_CnslN!EE$cAHVU(KMR@ZG8x+N z=UA;MFK_H_=;a6W{f2*y-~s{c2S*?0Fz3YXrDk#4zTRFkMn-kBVMuT=Gg60}hlhuQ zW0HYofLZp2Tfv$H7z2T@TJcB{dNBWBcakqs(6}Kg3bu^BJzrpn0t7J1k&zLwGQlvA zEtB11Wo31)0y9T&0bvsExjZ12q1G&ZHsxQ&f=5;kb+NPKU^Gc zUP~UEwGn;D>(jk}Ko*KP+?~&2l=S|Etag7_SO|{YHr>dWk2XDlhg*ZKarC2AE)y~Q z4REK?N_+g#>VDGUFA4d zqoZGfZ|`C6TS*b}>U0HQN|Qu}rcs3=W`XZG)tHB)CEUCrgKXSKOBimP1RD3n|A$ya z&+cYegz5~4U1nPyE*{%_%en1ed=n|A5OIM}4z8W6-S;t%>;gSKJ#b4u(+kNxgkWQo zARUX3hHz>MieA~p+<0kwJ3AjRBQ{+xzWn*32E1>yBiW1f21+fq1XcYgivw63=PcL* zh4COTh@flqL-_pM9G`xf`AE6l{q>Johd(Edk3<_u@|Nm+HXc}7CMG7@SxF<)U%b!- z?rb=i$jqCrSAz(DwI#9#(R3X}X(hb_&Z?!oJ(p8LQqtDayV4_XGP{+P6%V9It=IM0 z_QViDuSQjEan_1zA|8^$Wh`DvbtS*p6fjgxA#_q`Ne{Qq?UrRkiR1u|;4{ zg5^U;1qD)vf7isMz$a z_L{RVLC(_B(&nZ|`0*q`Z(eZC8+asl*nSuxIb8m+{NsLL*t_CA0>2mg=1YSPx%IX> zg?fIW_-=(-aRq_kY4=jwWmRQmUv%~Sjtjf$i~d=9(ajqRck^Gr?#z-20xQJi=*V0^ z{hl*9vHCs#?!!=0=}8Bj@Y;w!gHZDG=g-HFA>c@L!S&R1C9P_U+@Jaqv%B8GSNo)8 zb#t=J%S~I!yTPQytUp~HBz!v4o%%?|ZjH?BZ{PmmPLAdeqrfZ1ewy|x) zS_|y~L-Y0ayvxUa@}bkM@vSW_>nINCvr4GwyUsZ)(dR^wKN#v&rt%}RJ32bFJ*Du1 zHDpchBb%nDr@@2jRwpN?8~11OUtG#cMoGJANq_hD0XwoWWsu?A=3*b>j_*pvU@COm zxBmV*2!7UB8@e6p83Q&oEuszIzI{t8>O8}s!XUp3YMbiYY%UMqXH79i9EwnWhi>vk zr!$1awTOeoxvN)?69{<|^Vn|(>}Gc6`)jR?eV2b{`k|vilnda60O}(-&#@ZM!~N}T zZ%HKEJKbU$5Z2jb1+*N<35$uP6>{7oWt8^+La8T!Qaew|;6G>rBb2Ff2Aj&{r$_t^ zI}cP;I-ap8*=|Vr{U)eU_+vv>8tmYmbH|XO^DH#!iKgbi2x0=ZNsL-3w zLdNZnIxi_7gikl_&uhnDYF+WdEDoEVOb{X; z3^pEpagmQ!XuRaRjh6CQ(4g7cKpoAcyTn})inz)H!mp6Kbm%{E6l=CB^c%`DUP|Oa zGl4k7>9)n#ET_tU56uvUZ3-MR*V|P6m$Fig;buOwNtHxWJCmXQy!D=&mD>y7SUzDb zr&rjH{6gPo_7_sloXAZu-cir7TjyY5JbmB5$tb4F&u+&V(cheS? z=lzN~Gye8X{2FyGq}UX#gs?^`jVW#0zKN=Q$)cRh=}G$Zq6T%+GK%7@=$Hq&QK3w= zLsKoqbEqEX3+#ccXRY?ffX7)9rv!J#(r(;%jRN2 zJEwZ}`o??@H5Ju&b>7&wL2EH)P|+y#XcfP-bm00-Tj+UW(2>43nz^=z+v9%mGEc9C zLk9(jYYN4BXY(W2&HUGHgP=M5_(x_SG17ZFwxN5N`d={8tj&~8CcWuFb9ueVqq681 z4D#8hhxyY>C!GMbH}1}*r^!QLhFQ{jT5g0LqK-oX-oGY8@kvF5g~xoCi>X01)$a2g z#WkMGUYiTwlDPF+nw$NPcIP+kWN&Vzf;P?X1c42dZULg*G(R(g^cryuGz3(e zohhFO8+XI;(SCt?R^V)s9=c)Q8Ks-R0wA9Jl@&;sabIZ3n{V_a_{Z@MI22&-pY??s z!~5V`{?ih-DP`(!&PwEMsPNa{vb%l8pKEt?;z-18=8mt1sj0M8I|VA@!IV21A=VpU zk1)ZuKxU&;h++!q5cGT4X1A48YEwf|@q8nVf*_JLE48wUo6Jp>)R&u^8|*cfD!8}s zmU7&rjQNnI)pIoYzW_e7cHs}`Iw43@u;c$2(2)j3T04!+M;4h|kgxN{>B@Gi>e)?^rom^bzVY7)4SoPoj zj@#-_dWeVH?BZNI_ou(=0Kwp-h?EFeI+$iW=19{$c>UQegckj%^HKLbVs$EhQ%TE~ z3wyTT0S*VIW_^|+KGJmhF(o(0;e1zmYs&silL>a7pE~#wJbL{2@z0-*l@ycm;25c9 zKnKD1`6PM!kjT!g1fu{qxUjOk<54g7g%QFqw`hk>5A4t}Pph_%gJSyC?xz&l)(T&GPz*Wcs2N1uVqoXmH zg8EpnX=jOh7VccKZW~4c$Zd2q?~1Uvluadt{F~g|P@0;;!pFrpJDRenKyaE&wRQxB zhleLLj`Kv)WW31a4e!m-&Gt{J+obwLZ4OUKO1d6&=B$`fJVX6LPK?*jq0hSdWWwS{ zt{<M)UD*_vD%954kxrstA zOCFn=nyN8g0*+i-49Vy3Z{*$@ymfWW9D8Z+;6P6jIk;@a&Gg|MFOuaEag|jF=V?qt zHvCkViwXJpCGdny9*iN zK7*XR(+QkeEP8Q^>va+Yz#|{A;6+>Y0TUi`@qK^_w0--U(X#5udFvYXjq1Okl&K!WOmrfFP#EXQ37|kDFJpu_zxaMb{G2& z7YK_$j5wqfbq)ItWpQz_TEWNs{D|V(01U0|;waivWhL{Wd@m78e(R#{=RR;ggP)y*c#(5j5B@-~T7tW%9=km?sF? zlai9&=aDsF`&IL=IlPB`C-3hB=40Ra{;vr{5uCKJsQYvR~!qU>J(G`Fqfws{{m*bhuAAh(a?y&$41ZEzJ$o==0tuNKskM5kK`T*t_Km?T( z2$FQ&PuzTbrf}%1vRia$F)=Y(5l3?fZfDV}SIpAVnGL|wO^3?yGC=@(@1CUF41pOU z40v~=A3uD6>WS);V9#=SZ#g*kaJikfvoqguu>dCONJvN^p%-sX!O_2ca)OtZmV)*4 zgbA5cURg;3Y5~U$vI+s^=iuPr;hAYXSC*WRaH(n(OygxaI1I#Q>%gg-&u^M*3RoSl zx3ja`k>Jw*S0Kz}%!I6!eXoY;!5dqas5G zih)z?!Go*ee!98?p#Q`6I1V{IxqnO%!^!PCpb+5{m>~p^SJEj!Y90^~UQ2v0*oiVq z5||Az9$-R_=k#A%jMWMmpg#_*FBVkA5Ea)lAs=ZQ7%aL~4{4R%Y^tfEY?A7v3X^~W zrb$pp2t@BgkTSuh8d1d9uX898NoB8g7}{EjfHcC>C9D=jgrE;I=A(vvWC+9m`;t7? zT2p6lI9?v8zle_DCxDp)*!BcqGgtjv^0Kh7Fz84{MN%;ikzkRZO2mF7V@ayCloVfy z-h&4dqb`g=bDd*To)-)n_DfPTe@U$JQ0f`L03@jo_9z2`D@G8ihx*%8k$wS(OEG+p z4azxU7&KCyhXl45kKwoJ?ndwcq?+sm&^gm*5Qz)=cN0m?b2&XN?OJzsnvhU3U;Rrz zWWNWylfF^ylhXR>IERuNE~~Yvj-S8v3uy$esa3yBj-@Tg%O_bFlMv^2`1P)|dp=$; z=;*TH-sa+>hv|JCPa(a)^@p!i!#-qAqewtV$Hgb%S@T^jDe5eUI-W^nL`&r5HaBk$RlBRHbd2QW zydx*y&y)!wZKPC0lZpLnbtXU1-?m0%Bs^DU2$EEPDQ6O~pDh<)Xrz)_Jky?-uqVBZ zbUYdbn95*jXc%{{ z5)~EwNNG+FrkD*GuwGzg-9_^yazE&J-^dld!Qza%YS10NKkCANv9$Dn`z(s&nf2+e zuODeKW<-Z}-X6McdF?2>##VEn&PQgRp>b=V6ps*Qc!_*pdT+sV%54^ebgTK7#B012 zmiY)^8ohs^urh*^`HiRFS3N$u-njR}Dl4cVLUDmsRBf6s-2Y&$Zf9qRRK|F1YY=uX zE0e(-?lS&T6l%UoZC3X-&uZlvOQUIp{XwSGxrP$N*x>Hxsghc@$Ldo?7>g66sqWj! z;5`>3P~;cWl#vWb%&o1#_=UmMko43Ahrpu+=>T66Mrr8&?=;*93Ep@qufwQ|Yf^rS zRu3=aXiBCGg4roC*@z&fy-fLIEJB5uS@2(oT+yd8H18F(zI-(k@|DVI48aX5V?h#| zk)eB8PtGw7J-t@l;KeJa%j%aB*q{OfrHvr@Hu~F&aM}iN0yF+|o|!xUU2O;8BuY+6 zX-y8P2F07$kY<6^*?Of6h=k_mhDtS~sw1ts1|P8WcivW1{8;oD=%F>O5OQ)JPEYyH&Rm#i47zTXhdQrGoc@*9sPf)C;zgCMCY2dC3CtM~=p=xx0hBlv z3nmvT@`JH;oHNkYc)I9De7KNH$;<0t78HOgGRWQGBEDN}L0%n>km4$=g&X?-isphYJR z(EV?xe!MHqc@7rBEg$mgT_hz{HFTazr@-n4ok=4w^g@q+;A(T_lhJV*6$#Z6WX(H1 z*tPWf`E}lMggvVt5uR3{=ZyUVmh%=id&h+o24DFS0mV-`1=a)@n`&S-AIe<&dNs;@ z+{b?o=kEPp5pzb89Wg%aVBIRn8ke?IRFs!zbhh?F9AD9OBM%3yN;Z#0R?wfci00I{ z>})-;p#!kEmxhLHrRi7`UnHyWtG*Pn*^DN45EnLs1bv!?7O)C?erk#BgSRI1y#>>+o0?Qw|GOzmbQhX}Y-X3qszv1R0xtU6Q8fEd z5KkUzVUL#p*2^X#QJa$!!h0_9I%b&!%ymAI@`Jp1ftK_vOuZx^F23{&HS1qI}_)b`7_Jm%u23sCg zq(tn80(JGOQA=QsfE)JMMl&91<2T+>D*!k~OzV@oIgVXlFW-u83#*-BlTO3VV&i%{ zV_*gW03|3IDjNc~!U#E~e9!uN98!TTyS%-l0|a}PDxdEGi_2(3v=Aq2fbFHX2;gTZ zC;$g5@$NO1p<|(<{=i0=);BglU^A>GK>YXEdjv=ol{{OK>wV2t-ag8vLoEvQj*w8^E`fcp=!>i;3fu zd?mofUcuS6{|aTiu}uoe`?HUdNn*S4`TJj1{drYY6$otl^z!NYhVC5u4h=d;z0@$uj~UHcC4&(NC&p86&rg2<>IHyr{JPOX6a`06ED+7rT- zlV`Ul=qNEW6Z1X@1x#IC*AU@E;jB~89xNxPO@I?vSW=SD;o{&htpYS!G8TxlpSiLx zg5YAqTN2>2N^x{3l~gEj`GNbK{A>OaPJjDJ)I8Z3fC{H}hNI5QN!f-$^*-43YOsc)h?V1Y3iNX#0V3@!%xKjLo5-@=TmRmz6O30 z$bxO0aE$QQyu3V&Iw`yY6s#u#7M)@iD7K9sAdLi|TzYbHL}M=A8;lHNc4p?Gl@+1P z*1*7kI2}oe0)_=WF2}VEhpys%5f7IDh4_$*N>4H2q6sC=!N-98-_6ap_I`H6KLzGn zea{TUQ@~&5^j-N=+ck}aP z*#1V3j0}KK0Nx0A;|xikgklovtiU}^BMPe10&h8o?FH~RKM3S2FMvBXI3+ z*(=*?RN_5}Fr{J+8Nxq9yiG6R)vFCqp@-a`UcBLa3m^}$o09k%+#=Lvyug7pGBjLJ zIIBo*5kd3(g>cmT5fj;h)kO}D0D){MKQ}kfkO97NK&h*}XA8GQojv1b2v_Q3a18hLVsowW|%eDI47qs{*rhZK@O;t6he8tD(5ze)sQF9O>NF z&jDntmC9#=DO2kRC~5L!iz{^7y6B_|XY#{QF#=j!<3uviFk?8(!-ImFn)Hg`YqQ2c z5QJv=ueYg>?)U>zIp*>~7wUu7a#PbJWmsY$aR?!TV#Of z)b%aE56#1t`U>Lv7H4|c?mD}z&)hB1i280|L2fqhVacsqbVp4spIXp$su^fPN{oG6 z+)7P$>B$o%YSbKa^7UBDV$Vp3q+X#Jyw*%?kw~}=Hmm;*0|#aRAMz{&jK%lt=-aTjg3_10P5qj zD>~ut4pd?QCe-fElz_#RCLz-i4tn0L*Ekua7MfK{mCb4Ky&MIEZj{`OqLt@EGWssO zdh+B+)&TjPe{prq6Ko17Y1>|=qekTJUAo$aZYWS&3U2T8smtWe`yA}JHUJl`?dIHF zXGE^+4JVavohf(Fs;CO?I!lvF|8q?;M?02}7hR`Yz7co;%mHwrNC@Dp%kSPVz>u5E z1F;PzA086wsh|S8ga?25Z6rSYsRidZtxNUe>6UI&y*8c7J{}fm)0ujmg_-%0ALXr^ zGG*Q_?WHDY`ovuS&FqiSFHDm@iIDspGPgdlfwQv|+-8&s-CmaE2~q2O=)*Qj@{W;2XFLdnWe&Hv&>RbTv$MYLhIR!44&pmsv{g0D3Hd*wtW_GJNypbkkoBhg#lHb-cYT)5IDwEfj_DP8X-Lo5^<41=z?eT!?vWpp=qd76S$Dm7{+wd( zTxMco?tww63XRCKk5(O2qv2G%hRuV@UY7+QekBX@^ClB*#_)OsyBIV+epqT7Nls3_ z0amG&58%|o0~HjSswM(!%|C}|<|?kGJN{SJPPf<)5Nix2?L$y@fVej-m(*TU--{8w z3k;uKy?*N#s>!%cV2x}1kFk0BY))Pht>=2=ROIcr_bB)J7odl%_F6HlR1317uE@^* zH0u_y`Aun){MR4-aH&=;cUHdYj0W5Rj-*5}h%^(s0zBS5LGIE@IQD<3|sn!WD4D$3?+5baYL1q5e`>43<9KTAri?3_ttby#Ha|C3E`!zLFI$C~yevXbjhx!7u?X?MY3pzgJSqBc! zSg6r%)OhYQh_U0`Q3_gW`SZjV-{U#%eG<`?^iosn2Gr65j3strmvCp1ysP(>f=l&m zGC8}N2IV2%r25k~9ZutXWt5r(hV8cFQOF`)Xrh*he=+iY0}%SUCC0}wJL_rJY4*k5gIG4dCuTjPopdHwv}-MeWrK}T`)5;b)~A)k$RSgWEDpl8za zN1yQ-e^nGBKvhobu|%)JBBJzhMFPxeI~e!D=?@$?r0mWkd5Ld6Wsw5l3#yqKu z_E_4uW--<6F59NRZ^U0crC};$3Lm!=!bq!YK@2KgXcb@-8cmQHFt*wj(kZSwg|*n}oczTk)09 z8NMInk?ub&&+&@+s&23<<4}uWtFx0+Y)p*bVqVJ5rGmcQd70zkK_7H@L=B*s5A9YM zPbPy)npay>^K$^V&zE<{0N)gKMt+q_MkcM_E=@?^p)iY~b3z5Sv8MbIt^9SL-lW8p zxw&5?Y$pCz89FdZ792~2^)47aTli7Gh!jg%tW{h+SZp+fMEn=4w+4)Wi{+n@miqFg zf1j%8x8SO`Zx_{r_7Z=Q7AELGQr<$2vum8kYJe)*PcoA+p40WqyAS|ce|KJlmvbwB zT3A>BGUknngj%hJ1sxDq4_;L=g7+yweBF11ROob+QXGs4uDdEk9bcI4DJGSE+v85d zfxMXWXvW4^drbxzdSv+L5ChHfSp0t7vV}lpL5YivEu!}MELay{<60doWsGG**KMew zviN2TXZW=94%}+Tv!@8>P&2GbHK$jE4O|2D*+2wFiJUtF7o zQcrLwG*$tacLPW!lDG?~trEp~Su*?d*D>|V)n7_~v#3MpIQ=P(*gB#`n9x<>WX%oW zXCmpDH<|eO(5pem5>gFEd&?>OX5C5L_tN>UM7gOyK?K~H55fhFpvY;dwT-MJ<^xFkX&+A=l&f$Q`nZ_%K_@+P*oTCv zc)@b82ji16%yi7=t5W0Vs2@e&jgXMpOcrt&;E_fi?@t_$P&C!U;XA;u%kd zX$!Ai2dg)&mhqr*>rt-15<&Ix(LU$(lOzHT^>p+xJ@W`6BQOmRVcUy+k%7y--bgPC zVAUK7a*{AKa=hM;lwSOKAn$PC1=ydC9mt2Je+~DW#6$p%zegM}M9Du6ym_^$uD<@8 zrN*GkUprGq&yC}sfoub@CEsx#kN!mr@oEH7EYsze_*eP?;&~?>`Xp}1kgmJHAh`pM zH$d22!4S2_F6y83sg|s6n8!y)V={8Cxwr~4_eJ<=?1A_}Z9&h&(9qD*lEnyj;FjuL zV*8|LdSSBsF(3~k^ihO_L1Unl6s5`&9@#6xSB3MAVZCx+vr}$IG5!9`6ei&V6dH>P z7$@jdsu^0XnW)*MxuMCTrTyWDImv>R#l3jx%P*nZo|#v8PW7Ku#xdupWK|W3mAa@W z#iV;_eGTB>b4kx*h+*C`+7=vH1E8J;`X%Ss3lJ>EVge{^5}F%PyysN0kb;Nj%-4(6 zZI9&sU_d6od|bZ2zU#7x8V-}KK%biPOb^Uv)jFPgfK zdD(y0CzHNtUkDeAwCE+Wsg6{+Fd9K#U@@)*E}#hNZKE83f)xVfb&H zu*Mnkjs>}^#lhb7<3Iu(2#yC+8wq zG5&-&wxQ8ho54`M?;|7PK%{ikB4&Y+yn_6n^$EOS>r{P3Qi5$hz=oIx?#=>@th5|_ z^+a?{9HexP0CMtiKWdHvP9*14fK0?+h8M>+1c=okf7RB-%zG5FsIWUaUC1 z5YQo96gmZoM1qEC!WqRqI5;_h(lFZO3{E+sSq~bHag95=ylP-=d4j5Fm3q&y5RGd*RkVz12p8Gq?nfisw9 zV4!TNsE(B^q}uBI(%z3LuJC`=LKV3$3^Nvj4#~Qnw=;U&$epji6JYZeu559);c8mt zUeM~1jBC<(OeK3KpaRPHuwSeqY^q=A$Z;O4Wi?BabX~dST09;T!QKft;lHmOqXKRE zGD;{*;4|=r@o&`Xb>0Rmf(=XKaehIX2QhGF*ZRFJnr9Lrf^iTcb*hnD9O7U6tdr|n zH_pe?A9NHq-n*Rf>3*?zjr|NUi{F>6rSzfg!XJ7`<;ff=>Z3QEWS4M!5uqQ?_XK%L zH!}JrSW-W!e>lP_<-2ux^P?Qmas4l8nar}8@qx;s!`-?prB=m0iA1Ah2aqdw&f>w9 zLoiHEfsy9fpjPzCaF71iyQ;uE4e5Z6Oh z8_@fnoosHi0f~FvfzBewPD`)*9R|%hr1GKaX-^SS`DU8+_?wyUoz8C;BgvDIv;hwn zhYRMPG#|O~*)Y|rS*K3%p0`exTtLJV zT6xRgM%&}QF8lQdx^4!XRh@xeUNTBD5LI9Ql{16lrC#eg)5%Y2XKGZM)9)nrk!8k> zN)<}*-ncWLDOB9{Lkn(Jxg!{8)oMj@bkHzEo;+&wE#>y6dE2N8{73Q+J}^oDG-kV5 zg~t-L!Mnc_b9Y6F$2{UXsQ)2Lr#v(_a@)a&z5m?pLH>~|MvV>C>4rqo+AVE_xQ!$O*+2%MXkL}C|Gc!M~jL_AXJ+5N#F1#{Ta{~BUcFLx~y0^wc)mSk2hRmsq>8{@9C>)iWddz#85S>payW6CI!`IQ$+jl8xu zU6z-$zILRTszs6|AGj^^`!#P)@>>~rdg$zJZkiqj!e`cANR*=Z2cK~_9=%_lR%%w- zdXh7LZ`xV9Gzd=dT`D<~OJ`VVWbD|Dh?HwPjCK2WQ{GeeAcirCn&aN1P1JPzpfAV zRXso@ml1Aja7%^3quP&wR6{T zUrP>F&)i>aPe-x~N!1{(Qlp7}9|}<8X$rgP`C*CA3x8T#8Lfy0Yu>Ba!*xSYFa{}L zY*7fSR-MUL($k+oWEkDgNd5)|MZzR569J=a2UIi3_LWg<4dvhJi!#{^MJenNzFD`@*V#))q^`9yc8Ob>jIdxq=xz_PZ!&UQ7T@}#M z?xK2pDg6-bdVn>GN{N3ovL*yF+EGB}1FaqpI90fT%;O<^qho3MU9M&BF7)}mrG1J5 z-xTC6XJ3z5RyYda9vC)SfC|iU5|EXMA?>a_6*nJgu|rz6Rd*+0-kp(7Tl|(p?Sx_o zx_hw6o-Y*shi$g}Gm>9Wnb(DK&DB3=sKThget-7K<2b`WZ!t4&vB7G@{Z&9%tH%E! ztgl~%oei>%Hu|FxXaPo70|ZS#C!#pK*w<&d@*eCx#PlE<8>=F4V4WA&O9exexc?A4 zx>CC*%(SWx6k=9e6X@9<_8cvRCsh*|0}@Ol{(KBra2#th#u~$bHCq3*Mp1Hx6OxcBTE~I;pl;cILgA)PO!&NW|HvbGf7Oaa&Km`U}^u+W0UwI5XC~`b3 zLn!ws+DaZHax8Jj$9Pucc)+>|g#SPPp!|ie6Pyja8D`+e;ikyrojnJfUtDYxu+LAz z12T$KeYUgMSfU?8IvRnok;lXO`jpDQnH3`Zff5@b-xh7v{ZfqOfC>+*u*@EC5hqk> zChwp-aY=paO)Z$uVzrL4yfl>{_$0z#or<;scRz?Y4l(gO`UKeBPo8KT8i7!l^@B7J zrvSFgVs9cFT#6Cgkovh6`XDVoA0+U+2D0A6a*?xy2zne3cDgzu_GHczso{a06afRc zJYzxaruRI1@^CH8#n6!ED6SCX+~S1c$#~DRCBM2?@UXz&W-ydV4*o7!<_(^03+Z@u zv=xMi2;3|&l*HsshUS{ox)Ur54c)$*$aV=Un}gI)G4|L-X1y_YxFo+&Z-%xAzbX?-ORodN7%6~hxV?r)E0Phd}C zPhn4E&*a65)ewZfmp(q&018mGG{M>W?QzTHPqzIW{Wtn$`|mksU?l^eWdUsQ`aO#A zct@!cuQQA$>P0k7Ofi8Nm~MDC{S*06xyMfc-w<7lv+>G0r$x~JAP$NzPz#b0`XU3K z4D*K3#JuPn+E@j)_0ey=jlJMr8Um=CFhT75JZ9h}2~?~$9tVDX%Dh8VII963U-1sO zhM@n{4+2Xe*Qr~T_uB!JmBMGzo@~F>udU9?#`YmE(0g|_#cylrOY)vS<^l(hVFA+H zoJ2-tFv%j~beIVFeI7`?)x!B;0kiZX>Sjbwk5ZP7I%6x$Q-%>>?xp z=4Fo7NVDt^CL~g*bmy9AUSfxSXurRs-J8n;yU!$;gGI$I08ME`#CeOhkaI*pvl-4x z2ie}u0F3|%%pj%@tN8D<9;Pu7w9b>#XNyehYd|E!4Lq5Z$GYAi^J1s?8Zhs8S}g$< znC}AwZe&+{pCI6k|FC)Nl2|s+i}+%A3jgki-F%Pa#)U=_8*o7eNM_1WwYorPG9K{QK}?ofIW7~#4|{GLtS0pmxU=TQjwE?bf51| zPEH2$vB%axlJ;-vPghr0%Q^te@cls0I}lioyLIrgtG%>!bOh?Y)(PKbUT1P?q?zv` zYfwT4JIpZR!8XWivR1K@JowcFG_@1{8(nX;3l{W9&S7#@hLZTMZLiOo?*APAh)D-R zF)SpKd8U;%9vM25n*pCo9NaCEWx$AGpohL|Trb*Sfyv{zxLr1Cxh!O zvWnqPksT?1EAc?y2oeYvJ~JNuiUgvFRED2G5;0U}0ZHEh;eg`y!90Kuhwx)1%3Mpu z+$O>B-DCNVldNoO%gHmNQNw#e2VS^Elh8N)Mh(!0t02)Yp!Q+grNW$2kaCs*WtW6( zgZzk=mKH5|-_zvcWa{V80*}n=mOx#Gx9!*laPna=BD?F9ra+_FsH)($XNAcR1w3(> zsU=8Q4v5kmY973T9yE3*4(k0cjhRxsf0MWAST0FL6n$SfMfbTCbIDB?NNI-R1h{NutGz-p>F8W8QeCoMRbKNA#{&j0YqKZ7x)=utan+495!5+JzP5|Eyn%F&Sd zebC1+La`N45?0)2=aG%zf|D4&ngzhbJRE#_(HjUG0}L;hZW1ZF!}n**B+>*d@D6>` zC17YHmwHdYDQqnd#@8C$vmg)i8w^>0@s`*zqtbb7Nxhn3Ch)m}!fwmc?7B8{9#<9y z39q7{<0BwCEye73$4A?ZVAWBWLE6G3i0}Njt5uL)!W6k6wfwom4aI!bqs;=D=;LhV z%)mW6nlJl4DMiNdzhsaB87Uun6JHm=c7CC_OW;?ZLV=mQE-QO_esxnBsGt^7j6wV1 zji0$3L!hfKW*n01gmYCu4)C)JuGMbDaMFm**%rEL#@SwthU>T1RnI#-b8H5>)k#1s z7Cg%@EBKm6JO93wf%f`?TRoXlLV|*}`t8See*xyAe-Umn1~&PF+nk-A=yLZF4Ywyf zwcxC%mZMa^Ij%>Ec4^pU3lM*mc^g0PX~j7*wDj&^gTo-7;mXGz>D<;$HiFf&$)jgc z;saQ7NV|?k|q*!^GjcBjb#@3_Fumy zjB_Kbpb)UJ-<68NL~emwZLFPbo)WpXxmAynQ=sR5amFFP6j)JYmLUVEAQZpnmX~r% zc2v)I$gvo{c+_Qse8lhH1*x*upxS_uX?y~gYFs~#R}^dx5S(?ZV&_11p|r1{K`YSG zMCTxW8_Y-+9GY+6FE~n1llY@B{SB4Rn)(?|Z91vK@d0pN9QwD#n*+3FA)v7FuVrm= zbi2C#x-?Os>h;?QiZR2CYn8yESckZ$5>`IR1_a* z`!>VEZBRZ_j0WNCMIy+6$0uJ3hF=6pqV*?S`E!t<1{NtQU>A~0CI;wog{->jvN>>v zQ&cJCHbtB_8I@Xd7qwsuz5eElS?4YeUfw*^640cmd{b=10T~_}_&>1s2|eb2oWhe* zDbfrIVr#$U)8RQhh&*N%;YTLb`sVd$Sw)6ftIsBdtPl^uFN%W=b4 ziW|%w3R1v@0qnOoJiE;X>xe**50Ih%%u!zykXC?%&&@s#o=r~EkITyk7Ub&jB|tlT zlw%?0hT?;L6HwvbgjxAeq(u2>>?A`wJ@Mg2c!Vpy2wGT)q^`|Ew)$fHDX;rb z3&cuFAXY-<&dB0-9ZQNUXEg^TB-Cf1R3`yO#=G$Y)Ub zk}q9driFe8K3Eh9?mGxGeO7p^NQGzdn@x$$l?CkS?qDkc-a>&|M$XwMadA{?YV1B; zCF`3D3D^!B!Qa(99CrI-N^`>QGCr#f`+P>PWZHTP0s*w7)*O2$_vd0?0Z8WqHn}$4 z3N$fB`rHlHgM&XXpV^t=r%67M3J|;Zn|^TQ717)Xf8vUt?Av7)xN8N@*hM9am5~a^ zj3W>+%G=&j5h~jSCq=(QAn+1Ec6}|l-~!wWK-9r%W2je>P4)+B9 z2E^TH!Im@0-lv-`<8?zr`g@&5y1Lc?Ya;25O13uNxB@eOJNPm&@gv}uTUr!p8ZnXs z<5!4#%WgUlm@FV*yMZ2U5%9d<=0ky`NlVdP2V9d@U0-Zmoggj1uzagAmJFSZeubnv!Br2SZo=afL5s85PMm*G_3|nDR~wekKGF01O>D4ICrl%L3+DwE>E+x(eKW z11`-t*eVU0g=G26T>+Q(;Qq6b%z+eiAYF!v>d5^1bVkoCKv=It;7TcA{OQSnxaY~z z%!dxX>7G@Uh+5=$!@;^r`sDftAk+FUUpYANPsd?h{Fh*Wo(w=0?9cQFU~A(IdrRD0 zGSEq!ZC(Vu$JN0oH$5sEwS(pxouh%%v7+FDu9v(&%DFAugv|&p!zPK$+#MVojE!GH z^WFZ41`2NW)fgusz(@N8DJdzDRfXueZ1u}P+Bnt_AhFG>))A~WL!nRZ|uF&L)O3AMLC-@n&ofq3bhZPh&QRld-#(f=3O*7S9^F6D%!X=o(f;3F3oK238 z4y71+;#=>-MDe9AV{`K(WZr}XBJwZlunHoipe^(}h`~CKMXk9B0nOS{!bR|>VlS?O-PHf%mc#pb~JFC4`Y@xaYUJd~k1mIDA5 z0WWyK?FW;&Xjz&0qt0jCVm%VOfY7u%?yuev1|s?q@Qp#>)XijFR(kmrQkw&vkARhP zFZp)*qo+(6LQxWNCmnyiV8o`v{aBFQi9;CnSMeQE#ulBKz z=$ZP=0`G}xKv^qwJ^(n3m=xpcR*;Mbx;g1=uQL?J68M15^(yzz$B23W&;sMhEd9Zl(7)eDIv;`Oqt%_>3;6#`Ml5P{qOyg zz4tn6uf5jV*Y&%u>${Ekj}Pi|X&EGK43>GQG*Qyp1J9zc)?90n|7+$4B;CX#wcHWqG#!v0lE*bbXqj0!G4t5dnJu8(B5 zF9@-Pi>XEYQ}`_Or~3>9Rau&E%NJPai~VZl-`x2kW^b}-lMM~L7Y|Y(TTxVv9CxOwO=}6-lOap_(qWJYTLs8YM2-q zzEd-b{2B(Q4o2y0)}#KcD~EuHG*1^u|-_^|#ves&d~(cC#~K z2d$u!m6erq(|(G)x)%~R_o%}1?m*)9pLOeCaL&GVSp4j%v4FCOrRw+#T``oJJF%!* z?9My7YWk7+Q-z2=nb$AxQ&ak#cj?#UzLiuhT(`Jawb575X+qXG4{3j)>D6PV3!i{t zLV=EDa??Sd7lAA(M&Y~|m%9TC06c;(k+Lv9m0v#T!I#v=_a$V&)w)AqY2|_68-F6Q zUxqZ!%B=S4;-B>nd8gN&Qa`2rTzNlXc>Z(uJyrWB#{e7Q@V(zqU(a*5E~^-5`E4S2E_-+Wht5*j)q|IANFlo(04)@akj6s)u@@^D z5@(#IcR+qp-Q&<6Qto{S6p<2|Q<47j2+SWd3^zou9Pa;hr$mP>l>cU}L@c=!*zRNW z4Wt!Ki9jf{>P6Hp^LeRR*~1EoD*BWP1oeExEHs+$=4N?paw$G(h98MiVXcZ6Nvnms|erTK3R z%G;;3i+n*SmDxklKn2d5X`303xzMDdi%~BQolr87oPwkhSe|p6TZKb~Q{_6{`FsR! z;*KVGTHQ~Mn_F78V$I4iVO4>2($KyW?UDI{pafua(B6S*n-c{K)smmpM6ySanhU#O zeK;qaznQvqkxj>2qc)i5Dd=W2C7AEo!KwR3H(YOz^Y;tqrK&W_)hQ>UwS0fWwOb=3 zq~+ z351uGnZnHYsXs!E2qDOl_;Sm?RD><3x?CAf0Sl38#>97pz7WeQI) zR7nkW0cUn-Vq-#PH3!*nWFFVNN0>N(hQ_}lXt0AFNBD7sgnyiq!aqdu4^jN%pt=Ab zD_SKp-3epoLL)OcH3*cyW%J9@k5qysxQr|>OTZ=45;!0eq`9N7GBaKY5tk4PT-$?d z`}HopUhtTJaToDu)lHC>ZfP1Yh;}RK%jv5f75PU1)2qCxGf(FNeQ6##&CJcTU2ze@ z#QV>lor581yL;mK=}tX`J1DGtb6W)geu!#F9s`JCApfg*P1CET`2n3-cebtQp9jyC zIc)hx5#oh_*N${ShEtN4A3`4QgIfL(OfW%O19Vt&p)CUe1mMnaPPsNRqiD8X@~reV zfBGxEn(`AkDkEd#C1f++tA%Lt5!Btfm|aw)t0G_ZJI$^*-o5{!F!F{m!tqy01yK%* zKjTnd6#Wx|MUwB7h_#%^2nqX*a?9x8;HR>flK(U>G*TNWiBtp1kt3gx$vUHlx%2G`~((R6J8;X`*6)ATocb@Rx%qJl--}FPHpH$1Y|#D+9<<_xb9KS} zR1!ujYjCa+qZO$36~Z`Dg!Y9o(|2HS0xYni*qAWI2XS!_=Kfj(bU_cja|ab^NXi%`SyDFj5TWrj~Lv?tc1!KmQo_1A6rS@z$>$1!z%W-hl!+Z z1j_xb^U$B-?+%ym{Q5{ZPnxRPEV5?s{z4rN@5SL(B`4!(=byAOD}s%9RpOv>LlYts z0zF|;!_EbKiGr{P0P&tUOvL+x`$`Dw8Z=;vsw!y7pd9=@OvD&Lz}xuOU-gZRNkD2r zRJ~(105`I+JNiV06WZ{c`;otL<;q^q);%z2_XEdaYimmu+FlXK!omU|gWeztWI_(} za&9M3h9n|uk-`knhXhKHd3fk+SLx9$wE20`40LNmqc$mZXQnGTZ~8+WLAfBzjO>RG zfy5B9&dZ*fnsTm<2u)E9uDo|qPI_l(;Qj1*^&>iH^#=yiGrzWXBgN7!8^B!|#lbWc zm-lxTx87Am*3*Z5Rb*=?S)VC-&xa4UHIX(%>0jc6IbIScMD=@rS`qLEyLCtdk0@w@%ytD1GvT@3@_n zm8_ygG&0JUpdQR&jz8lm;bee)c3RKXqgumhRLIVg$NoTxg#5=+*|6qI^cBX}go)@s z5C%f_UQS4S>~}~@9+WFp-)U8ahh=cjbWZ=u_U;>25HT5w1>RlFpFTN~ii+N%B!^)@ zxx^v-plKG&sEAu?*|k|>oBN6cFukR}F3pYV{J6z=Jkw+dG{B4PG&^uWMoXvHs9GgMa^_$_BvML%_vNQziwz)0|MLw*CR8x zNQzAU{JIi3kIG0(_!J*UH*VP}5o-8i7sZOSn&wfb9pkk7@7B^n{u zj50FAn{T)Pdg@j(PAxi7MddtHFzh54d3OD6)g!_rcskyImOqok;g)vlR1?iuatfe;(r1P4At zcSpAA>({yG8D5@wyb=@FnANF8G1}_ZmMEFrp!G-nf;Ic-v?Kwu1Xa!n%65c~s%7B_ zKhh}knLbmSNoJH4N>I9qz^?38de`yJzjsiA1U*Z5d^pgYeaNb_v-1N7_4ld%k*=N? zT9-skO%1l&_ykm-Jq6Bx4aK0v)3_N3#n}X72Et}=LO!oC#tMeMLO`|wR-iTgyx^v5R zMj&K72wc8>wUcxPBCQ7kJ&Kg$KW06ige`EY@skAURM^Q;KCQNVdQVsB@VmCQ6|Ag7 zNqjlNJw0QYHNCwKy`R1!s$|lK@{+X-Bv^X5Pq}Q^djdPX_4D))I5KzOwG?QNOKrRajH>g059YMpkb<0xE!RPU~8G51dMX@L;B z%YBp8*XY{nkN-TO#zak_ts}4s9R+8r`OMW5-$G*h+OT=Qr2qUlLSqMqqx>+F5rCdW zh?TF*B0MCdLOK=X4j&ruY*O7$sE~-<{xigT!=VGVw&LRAu$KDaT|<&%PoT_E)U>Z? zY9IKN`m|Us%-qL(&z>5M_=GPsAk}(V};p_KbN(n0^r|v;MCM1#zi!_>RHaBY}Z|*ZB{LuUm;o${7pf`R@k}p6E}z_%o1@$eW%D ze8e56*Ki>!cn-C1!|GAmPE0F9`F>4L>m-yq$0nl4pO^Qud*K7~ByeN|or1rcJkCI#@y@r@ltHPeIs1>VJkJiJ^U%m&IMd%c)qjegV%Kvo%oG2HD_mM;l=SA z&xN|Br85QNhI(maYB3jzgBf2MXldDZR##{I(J$p>te&r30&mHqn|603nhjvHAS_j9 zI?Pyki&`AiyZKo_`^4j4sujF9`E$l}ucqZQ#a>Tk{Vs5(V{c0zMIj89mDpj zoxd}R+G#VlZW(1|PY7B=&ZB$yO*ea`6?-(R3y-`kii%K8 z^8l6IHp3UB4+oh@XnA`ACEue2j^PNXth;-c3(+I&j+01hL!au}Z1xJDb`>FIw0?tz zzph6Z6lA87;AUd9uhgEsFkom=y-g_mGUPezI-FF6i(t4hF)>w6hbs&3bo0SKJ104oezlt8V-(FD9UV@*4U-KCSkcwe_GbblFVq;J4Vz~TpAPshD4q~K-p@%9!jc{DK2A^G&6x0oZl zX_)m)a!pIuGQ2%YDt*5!?7HRTc=)Y=OcjlI1+iIn>KE0U-7 z6-#6kEr{)M(>^VYcebcXw#pwnb(Cx!eC5j4?r$Yd?4}QUbH@G;!?Rg%_IewxyG)** znBX%mt|F&T;GK}USX!y6smaXD{QA|aptBPZeQ%8R47^d>yM9yip1MlA_cr!2tEPKK z7PgarxqQns|GQs^@>d}T$@_CP``JquMHO8%a_ZD>JTp*}f`XQF=JibO^h9#+F7xA& z_yxc6N|Z*OOU3gbfw_6|WM)~`rHz@BzxE6W%*y7)4$78{7D8*VKKvnzJnb|(a4Dty zUzc7Y2dgP7qy9fVEe&-H8)ao5l$P2_#K}C%{#GL0S)D3V6k2w>aPIl^gyY)iyKi|h zo_@!tLVq}b*LLaBr9VyoaTb9OTr(6eDi35WDMl8ynZQWm;Yh3#(=!8OtfZdbBXwMLG$;&&bvF z5k3X*9|!K$CdIWbM+z*b0en2$>9KgmSx#~1HNC5=>hgp~+Sb9{WA*|6uiW7o7Bf7= zZO8LPsG5`eu?gS?`zin1=ag31@sD%5*Q)1uz9deKsQr?ekpWt01egLLA>50{u54rq z)}OU7h`w1qdBU1Nk(L%aQozU4$z7EgQb&aYZ=ecaQ94hGs>ySMlh_>^ayo==W?f0Zq>_@P7b + + 10 + + UMLClass + + 250 + 120 + 140 + 40 + + File System +halign=left + + + + Relation + + 310 + 150 + 160 + 280 + + lt=<- + 140.0;260.0;10.0;10.0 + + + UMLClass + + 100 + 580 + 120 + 60 + + Collection of +Accepted +State Files +halign=left + + + + UMLState + + 370 + 410 + 170 + 40 + + User initiates a +File System update. +halign=left + + + + Relation + + 210 + 590 + 180 + 30 + + lt=. + 10.0;10.0;160.0;10.0 + + + UMLState + + 370 + 570 + 150 + 60 + + Check if a newer +State File +is available +halign=left + + + + UMLState + + 80 + 240 + 170 + 40 + + Update State File +from File System +halign=left + + + + UMLClass + + 100 + 500 + 130 + 40 + + Last Accepted +State File +bg=green +halign=left + + + + UMLClass + + 100 + 320 + 130 + 40 + + Current +State File +bg=yellow +halign=left + + + + UMLState + + 80 + 410 + 160 + 40 + + Accept State File + + + + Relation + + 430 + 440 + 40 + 150 + + lt=<- + 10.0;130.0;20.0;10.0 + + + Relation + + 150 + 350 + 30 + 80 + + lt=<- + 10.0;60.0;10.0;10.0 + + + Relation + + 310 + 620 + 150 + 120 + + lt=<- +[YES] + 10.0;100.0;130.0;10.0 + + + UMLState + + 240 + 720 + 170 + 60 + + Update File System +according to newest +State File + + + + Relation + + 150 + 440 + 30 + 80 + + lt=<- + 10.0;60.0;10.0;10.0 + + + Relation + + 150 + 150 + 190 + 110 + + lt=<- + 10.0;90.0;170.0;10.0 + + + Relation + + 150 + 270 + 30 + 70 + + lt=<- + 10.0;50.0;10.0;10.0 + + + Relation + + 150 + 530 + 30 + 70 + + lt=. + 10.0;10.0;10.0;50.0 + + + UMLClass + + 860 + 0 + 340 + 50 + + SyncEntity +-- +Map<SyncDirectory> directories +halign=left + + + + UMLClass + + 1300 + 90 + 230 + 200 + + SyncDirectory + +-- +String realPath +String stateFileBasePath +File stateFileOld +File stateFileNew +Map<String,File> poolOld +Map<String,File> poolNew +List<String> listCreated +List<String> listDeleted +halign=left + + + + Relation + + 1190 + 30 + 130 + 90 + + lt=<- + 110.0;70.0;10.0;10.0 + + + UMLClass + + 1620 + 740 + 130 + 60 + + StateFileOld +bg=yellow +halign=left + + + + UMLClass + + 1750 + 740 + 130 + 30 + + StateFileNew +bg=green +halign=left + + + + UMLClass + + 1750 + 770 + 130 + 30 + + ListDeleted +halign=left + + + + UMLClass + + 1620 + 820 + 130 + 30 + + StateFileOld +bg=yellow +halign=left + + + + UMLClass + + 1750 + 820 + 130 + 60 + + StateFileNew +bg=green +halign=left + + + + UMLClass + + 1620 + 850 + 130 + 30 + + ListCreated +halign=left + + + + UMLState + + 1220 + 650 + 170 + 60 + + update +StateFileNew + + + + UMLState + + 1190 + 770 + 120 + 40 + + get +ListCreated + + + + UMLState + + 1310 + 770 + 120 + 40 + + get +ListDeleted + + + + Relation + + 1230 + 700 + 90 + 90 + + lt=<- + 10.0;70.0;70.0;10.0 + + + Relation + + 1310 + 700 + 80 + 90 + + lt=<- + 60.0;70.0;10.0;10.0 + + + UMLState + + 1190 + 850 + 120 + 40 + + add to +MapCreated + + + + UMLState + + 1310 + 850 + 120 + 40 + + add to +MapDeleted + + + + Relation + + 1360 + 800 + 30 + 70 + + lt=<- + 10.0;50.0;10.0;10.0 + + + Relation + + 1240 + 800 + 30 + 70 + + lt=<- + 10.0;50.0;10.0;10.0 + + + UMLState + + 1230 + 970 + 170 + 60 + + Perform +File Operations +for Sycronization + + + + Relation + + 1310 + 880 + 80 + 110 + + lt=<- + 10.0;90.0;60.0;10.0 + + + Relation + + 1240 + 880 + 100 + 110 + + lt=<- + 80.0;90.0;10.0;10.0 + + + UMLClass + + 1020 + 610 + 440 + 320 + + For Each SyncDirectory +halign=left +layer=-1 + + + + UMLClass + + 1600 + 720 + 300 + 180 + + +halign=left +layer=-1 + + + + Relation + + 1420 + 780 + 200 + 50 + + lt=. + 180.0;30.0;10.0;10.0 + + + Relation + + 1280 + 580 + 40 + 90 + + lt=<- + 10.0;70.0;20.0;10.0 + + + UMLSpecialState + + 1290 + 570 + 20 + 20 + + type=initial + + + + UMLSpecialState + + 1300 + 1200 + 20 + 20 + + type=final + + + + Relation + + 1300 + 1020 + 30 + 80 + + lt=<- + 10.0;60.0;10.0;10.0 + + + Relation + + 1290 + 1130 + 40 + 90 + + lt=<- + 20.0;70.0;10.0;10.0 + + + UMLState + + 1220 + 1080 + 170 + 60 + + update +StateFileBoth + + + diff --git a/src/com/olexyn/ensync/shell/pipe.sh b/src/com/olexyn/ensync/shell/pipe.sh new file mode 100755 index 0000000..dc6f96c --- /dev/null +++ b/src/com/olexyn/ensync/shell/pipe.sh @@ -0,0 +1,6 @@ +#!/bin/bash +a=$1 +b=$2 +$a | $b + +# this is a pipe \ No newline at end of file diff --git a/src/com/olexyn/ensync/shell/pipe2.sh b/src/com/olexyn/ensync/shell/pipe2.sh new file mode 100755 index 0000000..826e21f --- /dev/null +++ b/src/com/olexyn/ensync/shell/pipe2.sh @@ -0,0 +1,7 @@ +#!/bin/bash +a=$1 +b=$2 +c=$3 +$a | $b | $c + +# this is a double pipe \ No newline at end of file diff --git a/src/com/olexyn/ensync/shell/toFile.sh b/src/com/olexyn/ensync/shell/toFile.sh new file mode 100755 index 0000000..8585b3d --- /dev/null +++ b/src/com/olexyn/ensync/shell/toFile.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +a=$1 +b=$2 +c=$3 + +$a $b > $c \ No newline at end of file diff --git a/src/com/olexyn/ensync/sync.conf b/src/com/olexyn/ensync/sync.conf deleted file mode 100644 index b2aca4c..0000000 --- a/src/com/olexyn/ensync/sync.conf +++ /dev/null @@ -1,13 +0,0 @@ -# -u update -# -r recursive -# -v verbose -# -t keep modification times -# -W whole file (faster if network bandwith is faster then disk bandwith) -# -# examples: -# ./dirA -- urvtW -> ./dirB -# ./dirA <- urvtW ---- urvtW -> ./dirB -/home/user/ws/idea/env-sync/src/com/olexyn/ensync/tmp/in/ <- urvtW ---- urvtW -> /home/user/ws/idea/env-sync/src/com/olexyn/ensync/tmp/out/ -# backup -# /home/user/ws/ -- urvtW -> /media/time/backup/auto/ws -/home/user/wiki/ -- urvtW -> /media/time/backup/auto/wiki \ No newline at end of file