>From b05f6e4f93769b5082bba25d3bcba6c6f6abcd43 Mon Sep 17 00:00:00 2001
From: Marcus Lauer <marcuslauer@nyc.rr.com>
Date: Sat, 25 Aug 2012 16:27:13 -0400
Subject: [PATCH] Copyfile should check MD5 of target and source and not copy
 if identical

---
 func/minion/modules/copyfile.py       |   35 +++++++++++++++++++++++++-------
 func/overlord/cmd_modules/copyfile.py |    4 ++-
 func/overlord/modules/copyfile.py     |   13 +++++++++--
 3 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/func/minion/modules/copyfile.py b/func/minion/modules/copyfile.py
index 61c6a4f..e5bf5da 100644
--- a/func/minion/modules/copyfile.py
+++ b/func/minion/modules/copyfile.py
@@ -26,6 +26,7 @@ import time
 import shutil
 
 import func_module
+from func import utils as func_utils
 
 
 class CopyFile(func_module.FuncModule):
@@ -40,28 +41,39 @@ class CopyFile(func_module.FuncModule):
         return thissum.hexdigest()
 
     def checksum(self, thing):
-
         CHUNK=2**16
         thissum = hashlib.new('sha1')
         if os.path.exists(thing):
-            fo = open(thing, 'r', CHUNK)
-            chunk = fo.read
-            while chunk:
+            fo = open(thing, 'r')
+            while True:
                 chunk = fo.read(CHUNK)
+                if not chunk:
+                    break
                 thissum.update(chunk)
             fo.close()
             del fo
         else:
-            # assuming it's a string of some kind
+	    # assuming it's a string of some kind
             thissum.update(thing)
 
-        return thissum.hexdigest()
+        hexdig = thissum.hexdigest()
+        return hexdig
 
-    def open(self, filepath, mode=None, uid=-1, gid=-1):
+    def open(self, filepath, remote_sum, mode=None, uid=-1, gid=-1, backup=False, force=False):
         dirpath = os.path.dirname(filepath)
         if not os.path.exists(dirpath):
             os.makedirs(dirpath)
 
+        if os.path.exists(filepath):
+	    if not force:
+                local_sum = self.checksum(filepath)
+                if remote_sum == local_sum:
+                    return 0
+
+	    if backup:
+                if not self._backuplocal(filepath):
+                    return -1
+
         # Create empty file
         try:
             fo = open(filepath, 'w')
@@ -82,7 +94,14 @@ class CopyFile(func_module.FuncModule):
 
         return filepath
 
-    def append(self, filepath, filebuf):
+    def append(self, open_result, filebuf):
+        hostname = func_utils.get_hostname_by_route()
+        filepath = open_result[hostname]
+
+        # If the result of the open function was 0 (or -1), do not append, return the same value.
+	if type(filepath) == type(0):
+	    return filepath
+
         if not os.path.exists(filepath):
             # file disaperead
             return -1
diff --git a/func/overlord/cmd_modules/copyfile.py b/func/overlord/cmd_modules/copyfile.py
index 3f2263d..a5dda6c 100644
--- a/func/overlord/cmd_modules/copyfile.py
+++ b/func/overlord/cmd_modules/copyfile.py
@@ -34,6 +34,8 @@ class CopyFile(base_command.BaseCommand):
                                action="store")
         self.parser.add_option("", "--remotepath", dest="remotepath",
                                 action="store")
+        self.parser.add_option("", "--backup", dest="backup",
+                               action="store_true")
         self.parser.add_option("", "--force", dest="force",
                                action="store_true")
         self.parser.add_option("-v", "--verbose", dest="verbose",
@@ -50,4 +52,4 @@ class CopyFile(base_command.BaseCommand):
         self.server_spec = self.parentCommand.server_spec
         self.getOverlord()
 
-        return self.overlord_obj.local.copyfile.send(self.options.filename, self.options.remotepath)
+        return self.overlord_obj.local.copyfile.send(self.options.filename, self.options.remotepath, self.options.backup, self.options.force)
diff --git a/func/overlord/modules/copyfile.py b/func/overlord/modules/copyfile.py
index 9f385a9..f13fc9b 100644
--- a/func/overlord/modules/copyfile.py
+++ b/func/overlord/modules/copyfile.py
@@ -7,7 +7,7 @@ import xmlrpclib
 from func.overlord import overlord_module
 
 class copyfile(overlord_module.BaseModule):
-    def send(self, localpath, remotepath, bufsize=60000):
+    def send(self, localpath, remotepath, backup=None, force=None, bufsize=60000):
         try:
             f = open(localpath, "r")
         except IOError, e:
@@ -19,12 +19,19 @@ class copyfile(overlord_module.BaseModule):
         uid = st.st_uid
         gid = st.st_gid
 
-        self.parent.run("copyfile", "open", [remotepath, mode, uid, gid])
+	if force:
+            local_sum = -1
+        else:
+            import func.minion.modules.copyfile as CopyFile
+            cf = CopyFile.CopyFile()
+            local_sum = cf.checksum(localpath)
+
+        open_result = self.parent.run("copyfile", "open", [remotepath, local_sum, mode, uid, gid, backup, force])
 
         while True:
             data=f.read(bufsize)
             if data:
-                self.parent.run("copyfile", "append", [remotepath, xmlrpclib.Binary(data)])
+                self.parent.run("copyfile", "append", [open_result, xmlrpclib.Binary(data)])
             else:
                 break
 
-- 
1.7.7
