def syncFiles(self, path=None): app = self.obj if isinstance(app, dApp): homedir = app.HomeDirectory try: appname = file(pathjoin(homedir, ".appname")).read() except IOError: # Use the HomeDirectory name appname = os.path.split(homedir.rstrip("/"))[1] else: # Running from the launch method. The path will contain the app name appname = path homedir = pathjoin(self._dataDir, path) if not os.path.exists(homedir): os.makedirs(homedir) os.chdir(homedir) url = self._getManifestUrl(appname, "diff") # Get the current manifest currentMf = Manifest.getManifest(homedir) params = {"current": jsonEncode(currentMf)} prm = urllib.urlencode(params) try: res = self.UrlOpener.open(url, data=prm) except urllib2.HTTPError, e: errcode = e.code errText = e.read() errMsg = "\n".join(errText.splitlines()[4:]) if errcode == 304: # Nothing has changed on the server, so we're cool... return homedir else: dabo.log.error(_("HTTP Error syncing files: %s") % e) return
def manifest(self, app=None, fnc=None, id=None, *args, **kwargs): file("/tmp/manifest", "a").write("MANIFEST: app=%s\n" % app) if app is None: # Return list of available apps. dirnames = [d for d in os.listdir(sourcePath) if not d.startswith(".")] file("/tmp/manifest", "a").write("%s\n" % str(dirnames)) return jsonEncode(dirnames) crs = self.getFileRequestDB() enclocal = request.params.get("current", "") try: local = jsonDecode(enclocal) except ValueError: # No local manifest passed local = None appPath = os.path.join(sourcePath, app) mf = Manifest.getManifest(appPath) file("/tmp/manifest", "a").write("appPath: %s\n" % appPath) file("/tmp/manifest", "a").write("mf: %s\n" % str(mf)) # Handle the various functions if fnc is None or fnc == "full": # Send the full manifest pmf = pickle.dumps(mf) ret = jsonEncode(pmf) return ret elif fnc == "diff": chgs = Manifest.diff(mf, local) if not chgs: abort(304, _("No changes")) # The diff will contain both added/updated file, as well as deleted # files. Separate the two in case the only change involves deletions. nonDelChanges = [kk for (kk, vv) in chgs.items() if vv] if nonDelChanges: # Create a unique val to store the diffs so that the client # can request the files. hashval = hash((request, time.time())) sql = """create table if not exists filecache ( hashval text, updated int, pickledata text) """ crs.execute(sql) updated = int(time.time()) sql = """insert into filecache (hashval, updated, pickledata) values (?, ?, ?)""" pkData = str(chgs) crs.execute(sql, (hashval, updated, pkData)) else: # No added/updated files. Return a zero filecode to signify nothing to download hashval = 0 # Return the hashval and manifest so that the user can request the files return jsonEncode((hashval, chgs, mf)) elif fnc == "files": # The client is requesting the changed files. The hashval will # be in the kwargs sql = """select pickledata from filecache where hashval = ?""" crs.execute(sql, (id, )) chgs = eval(crs.Record.pickledata) # Need to cd to the source directory currdir = os.getcwd() os.chdir(appPath) fd, tmpname = tempfile.mkstemp(suffix=".zip") os.close(fd) z = ZipFile(tmpname, "w") for pth,tm in chgs.items(): # File names must be str for zipfile pth = str(pth) if tm: z.write(pth) z.close() response.headers['content-type'] = "application/x-zip-compressed" os.chdir(currdir) ret = file(tmpname, "rb").read() os.remove(tmpname) return ret
def syncFiles(self, path=None): app = self.obj if isinstance(app, dApp): homedir = app.HomeDirectory try: appname = file(pathjoin(homedir, ".appname")).read() except IOError: # Use the HomeDirectory name appname = os.path.split(homedir.rstrip("/"))[1] else: # Running from the launch method. The path will contain the app name appname = path homedir = pathjoin(self._dataDir, path) if not os.path.exists(homedir): os.makedirs(homedir) os.chdir(homedir) url = self._getManifestUrl(appname, "diff") # Get the current manifest currentMf = Manifest.getManifest(homedir) params = {"current": jsonEncode(currentMf)} prm = urllib.parse.urlencode(params) try: res = self.UrlOpener.open(url, data=prm) except urllib.error.HTTPError as e: errcode = e.code errText = e.read() errMsg = "\n".join(errText.splitlines()[4:]) if errcode == 304: # Nothing has changed on the server, so we're cool... return homedir else: dabo.log.error(_("HTTP Error syncing files: %s") % e) return except urllib.error.URLError: # Right now re-raise it and let the UI handle it raise nonpickleRet = res.read() filecode, chgs, serverMf = jsonDecode(nonpickleRet) # Everything after this is relative to the app's home directory, so # change to it currdir = os.getcwd() os.chdir(homedir) # Read in the current base manifest try: baseMf = pickle.load(file(".serverManifest")) except IOError: baseMf = {} # Save the current server manifest pickle.dump(serverMf, file(".serverManifest", "w"), pickle.HIGHEST_PROTOCOL) # Check the server manifest for deleted files deleted = [pth for (pth, modf) in list(chgs.items()) if not modf] for delpth in deleted: if delpth in baseMf: # Only delete files if they originally came from the server os.remove(delpth) # A zero filecode represents no changed files if filecode: # Request the files url = self._getManifestUrl(appname, "files", ustr(filecode)) try: res = self.UrlOpener.open(url) except urllib.error.HTTPError as e: dabo.log.error(_("HTTP Error retrieving files: %s") % e) # res holds a zip file f = StringIO(res.read()) zip = ZipFile(f) for pth in zip.namelist(): tm = chgs.get(pth) dirname = os.path.split(pth)[0] if dirname and not os.path.exists(dirname): os.makedirs(dirname) file(pth, "wb").write(zip.read(pth)) os.utime(pth, (tm, tm)) # NOT WORKING # Need to find a way to handle re-importing .py files. # if pth.endswith(".py"): # # if this is a .py file, we want to try re-importing it # modulePath = os.path.split(pth)[0].replace(os.sep, ".") # thismod = os.path.splitext(pth)[0].replace(os.sep, ".") # if thismod: # print "THISMOD", thismod # sys.modules.pop(thismod, None) # __import__(thismod) # if modulePath: # modl = sys.modules.get(modulePath) # print "pth", modulePath, type(modulePath), "MOD", modl # if modl: # reload(modl) os.chdir(currdir) return homedir