eric6/MicroPython/MicroPythonFileManager.py

branch
micropython
changeset 7131
f75e990caf99
parent 7108
4f6133a01c6a
child 7137
4ed2573947ff
--- a/eric6/MicroPython/MicroPythonFileManager.py	Sat Aug 10 20:06:37 2019 +0200
+++ b/eric6/MicroPython/MicroPythonFileManager.py	Mon Aug 12 14:53:07 2019 +0200
@@ -11,6 +11,7 @@
 
 import os
 import stat
+import shutil
 
 from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
 
@@ -171,7 +172,8 @@
         except Exception as exc:
             self.error.emit("delete", str(exc))
     
-    def __rsync(self, hostDirectory, deviceDirectory, mirror=True):
+    def __rsync(self, hostDirectory, deviceDirectory, mirror=True,
+                localDevice=False):
         """
         Private method to synchronize a local directory to the device.
         
@@ -182,6 +184,8 @@
         @param mirror flag indicating to mirror the local directory to
             the device directory
         @type bool
+        @param localDevice flag indicating device access via local file system
+        @type bool
         @return list of errors
         @rtype list of str
         """
@@ -197,26 +201,40 @@
             self.tr("Synchronizing <b>{0}</b>.").format(deviceDirectory)
         )
         
+        doneMessage = self.tr("Done synchronizing <b>{0}</b>.").format(
+            deviceDirectory)
+        
         sourceDict = {}
         sourceFiles = listdirStat(hostDirectory)
         for name, nstat in sourceFiles:
             sourceDict[name] = nstat
         
         destinationDict = {}
-        try:
-            destinationFiles = self.__commandsInterface.lls(deviceDirectory,
-                                                            fullstat=True)
-        except Exception as exc:
-            return [str(exc)]
-        if destinationFiles is None:
-            # the destination directory does not exist
+        if localDevice:
+            if not os.path.isdir(deviceDirectory):
+                # simply copy destination to source
+                shutil.copytree(hostDirectory, deviceDirectory)
+                self.rsyncProgressMessage.emit(doneMessage)
+                return errors
+            else:
+                destinationFiles = listdirStat(deviceDirectory)
+                for name, nstat in destinationFiles:
+                    destinationDict[name] = nstat
+        else:
             try:
-                self.__commandsInterface.mkdir(deviceDirectory)
+                destinationFiles = self.__commandsInterface.lls(deviceDirectory,
+                                                                fullstat=True)
             except Exception as exc:
                 return [str(exc)]
-        else:
-            for name, nstat in destinationFiles:
-                destinationDict[name] = nstat
+            if destinationFiles is None:
+                # the destination directory does not exist
+                try:
+                    self.__commandsInterface.mkdir(deviceDirectory)
+                except Exception as exc:
+                    return [str(exc)]
+            else:
+                for name, nstat in destinationFiles:
+                    destinationDict[name] = nstat
         
         destinationSet = set(destinationDict.keys())
         sourceSet = set(sourceDict.keys())
@@ -224,87 +242,153 @@
         toDelete = destinationSet - sourceSet               # delete from dev
         toUpdate = destinationSet.intersection(sourceSet)   # update files
         
-        for sourceBasename in toAdd:
-            # name exists in source but not in device
-            sourceFilename = os.path.join(hostDirectory, sourceBasename)
-            destFilename = deviceDirectory + "/" + sourceBasename
-            self.rsyncProgressMessage.emit(
-                self.tr("Adding <b>{0}</b>...").format(destFilename))
-            if os.path.isfile(sourceFilename):
-                try:
-                    self.__commandsInterface.put(sourceFilename, destFilename)
-                except Exception as exc:
+        if localDevice:
+            for sourceBasename in toAdd:
+                # name exists in source but not in device
+                sourceFilename = os.path.join(hostDirectory, sourceBasename)
+                destFilename = os.path.join(deviceDirectory, sourceBasename)
+                self.rsyncProgressMessage.emit(
+                    self.tr("Adding <b>{0}</b>...").format(destFilename))
+                if os.path.isfile(sourceFilename):
+                    shutil.copy2(sourceFilename, destFilename)
+                elif os.path.isdir(sourceFilename):
+                    # recurse
+                    errs = self.__rsync(sourceFilename, destFilename,
+                                        mirror=mirror, localDevice=localDevice)
                     # just note issues but ignore them otherwise
-                    errors.append(str(exc))
-            if os.path.isdir(sourceFilename):
-                # recurse
-                errs = self.__rsync(sourceFilename, destFilename,
-                                    mirror=mirror)
-                # just note issues but ignore them otherwise
-                errors.extend(errs)
-        
-        if mirror:
-            for destBasename in toDelete:
-                # name exists in device but not local, delete
-                destFilename = deviceDirectory + "/" + destBasename
+                    errors.extend(errs)
+            
+            if mirror:
+                for destBasename in toDelete:
+                    # name exists in device but not local, delete
+                    destFilename = os.path.join(deviceDirectory, destBasename)
+                    if os.path.isdir(destFilename):
+                        shutil.rmtree(destFilename, ignore_errors=True)
+                    elif os.path.isfile(destFilename):
+                        os.remove(destFilename)
+            
+            for sourceBasename in toUpdate:
+                # names exist in both; do an update
+                sourceStat = sourceDict[sourceBasename]
+                destStat = destinationDict[sourceBasename]
+                sourceFilename = os.path.join(hostDirectory, sourceBasename)
+                destFilename = os.path.join(deviceDirectory, sourceBasename)
+                destMode = destStat[0]
+                if os.path.isdir(sourceFilename):
+                    if os.path.isdir(destFilename):
+                        # both are directories => recurs
+                        errs = self.__rsync(sourceFilename, destFilename,
+                                            mirror=mirror,
+                                            localDevice=localDevice)
+                        # just note issues but ignore them otherwise
+                        errors.extend(errs)
+                    else:
+                        self.rsyncProgressMessage.emit(
+                            self.tr("Source <b>{0}</b> is a directory and"
+                                    " destination <b>{1}</b> is a file."
+                                    " Ignoring it.")
+                            .format(sourceFilename, destFilename)
+                        )
+                else:
+                    if os.path.isdir(destFilename):
+                        self.rsyncProgressMessage.emit(
+                            self.tr("Source <b>{0}</b> is a file and"
+                                    " destination <b>{1}</b> is a directory."
+                                    " Ignoring it.")
+                            .format(sourceFilename, destFilename)
+                        )
+                    else:
+                        if sourceStat[8] > destStat[8]:     # mtime
+                            self.rsyncProgressMessage.emit(
+                                self.tr("Updating <b>{0}</b>...")
+                                .format(destFilename)
+                            )
+                        shutil.copy2(sourceFilename, destFilename)
+        else:
+            for sourceBasename in toAdd:
+                # name exists in source but not in device
+                sourceFilename = os.path.join(hostDirectory, sourceBasename)
+                destFilename = deviceDirectory + "/" + sourceBasename
                 self.rsyncProgressMessage.emit(
-                    self.tr("Removing <b>{0}</b>...").format(destFilename))
-                try:
-                    self.__commandsInterface.rmrf(destFilename, recursive=True,
-                                                  force=True)
-                except Exception as exc:
-                    # just note issues but ignore them otherwise
-                    errors.append(str(exc))
-        
-        for sourceBasename in toUpdate:
-            # names exist in both; do an update
-            sourceStat = sourceDict[sourceBasename]
-            destStat = destinationDict[sourceBasename]
-            sourceFilename = os.path.join(hostDirectory, sourceBasename)
-            destFilename = deviceDirectory + "/" + sourceBasename
-            destMode = destStat[0]
-            if os.path.isdir(sourceFilename):
-                if stat.S_ISDIR(destMode):
-                    # both are directories => recurs
+                    self.tr("Adding <b>{0}</b>...").format(destFilename))
+                if os.path.isfile(sourceFilename):
+                    try:
+                        self.__commandsInterface.put(sourceFilename,
+                                                     destFilename)
+                    except Exception as exc:
+                        # just note issues but ignore them otherwise
+                        errors.append(str(exc))
+                elif os.path.isdir(sourceFilename):
+                    # recurse
                     errs = self.__rsync(sourceFilename, destFilename,
                                         mirror=mirror)
                     # just note issues but ignore them otherwise
                     errors.extend(errs)
-                else:
+        
+            if mirror:
+                for destBasename in toDelete:
+                    # name exists in device but not local, delete
+                    destFilename = deviceDirectory + "/" + destBasename
                     self.rsyncProgressMessage.emit(
-                        self.tr("Source <b>{0}</b> is a directory and"
-                                " destination <b>{1}</b> is a file. Ignoring"
-                                " it.")
-                        .format(sourceFilename, destFilename)
-                    )
-            else:
-                if stat.S_ISDIR(destMode):
-                    self.rsyncProgressMessage.emit(
-                        self.tr("Source <b>{0}</b> is a file and destination"
-                                " <b>{1}</b> is a directory. Ignoring it.")
-                        .format(sourceFilename, destFilename)
-                    )
+                        self.tr("Removing <b>{0}</b>...").format(destFilename))
+                    try:
+                        self.__commandsInterface.rmrf(destFilename,
+                                                      recursive=True,
+                                                      force=True)
+                    except Exception as exc:
+                        # just note issues but ignore them otherwise
+                        errors.append(str(exc))
+            
+            for sourceBasename in toUpdate:
+                # names exist in both; do an update
+                sourceStat = sourceDict[sourceBasename]
+                destStat = destinationDict[sourceBasename]
+                sourceFilename = os.path.join(hostDirectory, sourceBasename)
+                destFilename = deviceDirectory + "/" + sourceBasename
+                destMode = destStat[0]
+                if os.path.isdir(sourceFilename):
+                    if stat.S_ISDIR(destMode):
+                        # both are directories => recurs
+                        errs = self.__rsync(sourceFilename, destFilename,
+                                            mirror=mirror)
+                        # just note issues but ignore them otherwise
+                        errors.extend(errs)
+                    else:
+                        self.rsyncProgressMessage.emit(
+                            self.tr("Source <b>{0}</b> is a directory and"
+                                    " destination <b>{1}</b> is a file."
+                                    " Ignoring it.")
+                            .format(sourceFilename, destFilename)
+                        )
                 else:
-                    if sourceStat[8] > destStat[8]:     # mtime
+                    if stat.S_ISDIR(destMode):
                         self.rsyncProgressMessage.emit(
-                            self.tr("Updating <b>{0}</b>...")
-                            .format(destFilename)
+                            self.tr("Source <b>{0}</b> is a file and"
+                                    " destination <b>{1}</b> is a directory."
+                                    " Ignoring it.")
+                            .format(sourceFilename, destFilename)
                         )
-                        try:
-                            self.__commandsInterface.put(sourceFilename,
-                                                         destFilename)
-                        except Exception as exc:
-                            errors.append(str(exc))
+                    else:
+                        if sourceStat[8] > destStat[8]:     # mtime
+                            self.rsyncProgressMessage.emit(
+                                self.tr("Updating <b>{0}</b>...")
+                                .format(destFilename)
+                            )
+                            try:
+                                self.__commandsInterface.put(sourceFilename,
+                                                             destFilename)
+                            except Exception as exc:
+                                errors.append(str(exc))
         
-        self.rsyncProgressMessage.emit(
-            self.tr("Done synchronizing <b>{0}</b>.").format(deviceDirectory)
-        )
+        self.rsyncProgressMessage.emit(doneMessage)
         
         return errors
     
     @pyqtSlot(str, str)
     @pyqtSlot(str, str, bool)
-    def rsync(self, hostDirectory, deviceDirectory, mirror=True):
+    @pyqtSlot(str, str, bool, bool)
+    def rsync(self, hostDirectory, deviceDirectory, mirror=True,
+              localDevice=False):
         """
         Public slot to synchronize a local directory to the device.
         
@@ -315,8 +399,11 @@
         @param mirror flag indicating to mirror the local directory to
             the device directory
         @type bool
+        @param localDevice flag indicating device access via local file system
+        @type bool
         """
-        errors = self.__rsync(hostDirectory, deviceDirectory, mirror=mirror)
+        errors = self.__rsync(hostDirectory, deviceDirectory, mirror=mirror,
+                              localDevice=localDevice)
         if errors:
             self.error.emit("rsync", "\n".join(errors))
         

eric ide

mercurial