public InstallStatus InstallFiles() { var status = InstallStatus.Success; bool restartRequired = false; string oldFilesPath = Path.Combine("_update", "oldfiles"); string newFilesPath = Path.Combine("_update", "files", "HomeGenie_update"); string fullReleaseFolder = Path.Combine("_update", "files", "homegenie"); if (Directory.Exists(fullReleaseFolder)) { Directory.Move(fullReleaseFolder, newFilesPath); } Utility.FolderCleanUp(oldFilesPath); if (Directory.Exists(newFilesPath)) { LogMessage("= Copying new files..."); foreach (string file in Directory.EnumerateFiles(newFilesPath, "*", SearchOption.AllDirectories)) { bool doNotCopy = false; string destinationFolder = Path.GetDirectoryName(file).Replace(newFilesPath, "").TrimStart('/').TrimStart('\\'); string destinationFile = Path.Combine(destinationFolder, Path.GetFileName(file)).TrimStart(Directory.GetDirectoryRoot(Directory.GetCurrentDirectory()).ToArray()).TrimStart('/').TrimStart('\\'); // Update file only if different from local one bool processFile = false; if (File.Exists(destinationFile)) { using (var md5 = MD5.Create()) { string localHash, remoteHash = ""; try { // Try getting files' hash using (var stream = File.OpenRead(destinationFile)) { localHash = BitConverter.ToString(md5.ComputeHash(stream)); } using (var stream = File.OpenRead(file)) { remoteHash = BitConverter.ToString(md5.ComputeHash(stream)); } if (localHash != remoteHash) { processFile = true; //Console.WriteLine("CHANGED {0}", destinationFile); //Console.WriteLine(" - LOCAL {0}", localHash); //Console.WriteLine(" - REMOTE {0}", remoteHash); } } catch (Exception e) { // this mostly happen if the destinationFile is un use and cannot be opened, // file is then ignored if hash cannot be calculated } } } else { processFile = true; //Console.WriteLine("NEW FILE {0}", file); } if (!processFile) continue; // Some files needs to be handled differently than just copying if (destinationFile.EndsWith(".xml") && File.Exists(destinationFile)) { switch (destinationFile) { case "automationgroups.xml": doNotCopy = true; status = UpdateAutomationGroups(file) ? InstallStatus.Success : InstallStatus.Error;; break; case "groups.xml": doNotCopy = true; status = UpdateGroups(file) ? InstallStatus.Success : InstallStatus.Error; break; case "lircconfig.xml": doNotCopy = true; break; case "modules.xml": doNotCopy = true; break; case "programs.xml": doNotCopy = true; status = UpdatePrograms(file) ? InstallStatus.Success : InstallStatus.Error;; break; case "scheduler.xml": doNotCopy = true; status = UpdateScheduler(file) ? InstallStatus.Success : InstallStatus.Error;; break; case "systemconfig.xml": doNotCopy = true; status = UpdateSystemConfig(file) ? InstallStatus.Success : InstallStatus.Error;; break; } if (status == InstallStatus.Error) { break; } } else if (destinationFile.EndsWith("homegenie_stats.db")) { doNotCopy = true; } if (doNotCopy) continue; // Update the file if (destinationFile.EndsWith(".exe") || destinationFile.EndsWith(".dll") || destinationFile.EndsWith(".so")) restartRequired = true; if (!String.IsNullOrWhiteSpace(destinationFolder) && !Directory.Exists(destinationFolder)) { Directory.CreateDirectory(destinationFolder); } // backup current file before replacing it if (File.Exists(destinationFile)) { string oldFile = Path.Combine(oldFilesPath, destinationFile); Directory.CreateDirectory(Path.GetDirectoryName(oldFile)); LogMessage("+ Backup file '" + oldFile + "'"); // TODO: delete oldFilesPath before starting update //File.Delete(oldFile); if (destinationFile.EndsWith(".exe") || destinationFile.EndsWith(".dll")) { // this will allow replace of new exe and dll files File.Move(destinationFile, oldFile); } else { File.Copy(destinationFile, oldFile); } } try { LogMessage("+ Copying file '" + destinationFile + "'"); if (!string.IsNullOrWhiteSpace(Path.GetDirectoryName(destinationFile)) && !Directory.Exists(Path.GetDirectoryName(destinationFile))) { try { Directory.CreateDirectory(Path.GetDirectoryName(destinationFile)); LogMessage("+ Created folder '" + Path.GetDirectoryName(destinationFile) + "'"); } catch { } } File.Copy(file, destinationFile, true); } catch (Exception e) { LogMessage("! Error copying file '" + destinationFile + "' (" + e.Message + ")"); status = InstallStatus.Error; break; } } if (status == InstallStatus.Error) { // TODO: should revert! LogMessage("! ERROR update aborted."); } else if (restartRequired) { status = InstallStatus.RestartRequired; } } return status; }
public bool UpdatePrograms(string file) { bool success = true; try { var serializer = new XmlSerializer(typeof(List<ProgramBlock>)); var reader = new StreamReader(file); var newProgramList = (List<ProgramBlock>)serializer.Deserialize(reader); reader.Close(); // if (newProgramList.Count > 0) { bool configChanged = false; foreach (var program in newProgramList) { // Only system programs are to be updated if (program.Address < ProgramManager.USERSPACE_PROGRAMS_START) { ProgramBlock oldProgram = homegenie.ProgramManager.Programs.Find(p => p.Address == program.Address); if (oldProgram != null) { // Check new program against old one to find out if they differ bool changed = ProgramsDiff(oldProgram, program); if (!changed) continue; // Preserve IsEnabled status if program already exist program.IsEnabled = oldProgram.IsEnabled; LogMessage("* Updating Automation Program: " + program.Name + " (" + program.Address + ")"); homegenie.ProgramManager.ProgramRemove(oldProgram); } else { LogMessage("+ Adding Automation Program: " + program.Name + " (" + program.Address + ")"); } // Try copying the new program files if it's an arduino sketch if (program.Type.ToLower() == "arduino") { try { // copy arduino project files... // TODO: this is untested yet string sourceFolder = Path.Combine(UpdateBaseFolder, "programs", "arduino", program.Address.ToString()); string arduinoFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "programs", "arduino", program.Address.ToString()); Utility.FolderCleanUp(arduinoFolder); foreach (string newPath in Directory.GetFiles(sourceFolder)) { File.Copy(newPath, newPath.Replace(sourceFolder, arduinoFolder), true); LogMessage("* Updating Automation Program: " + program.Name + " (" + program.Address + ") - " + Path.GetFileName(newPath)); } } catch { // TODO: should report exception } } // Add the new program to the ProgramEngine homegenie.ProgramManager.ProgramAdd(program); // Compile C# programs in order to generate new binary file if (program.Type.ToLower() == "csharp") { homegenie.ProgramManager.CompileScript(program); } if (!configChanged) configChanged = true; } } if (configChanged) { // Save new programs config homegenie.UpdateProgramsDatabase(); } } // File.Delete(file); if (Directory.Exists(Path.Combine(homegenie.UpdateChecker.UpdateBaseFolder, "programs"))) { Directory.Delete(Path.Combine(homegenie.UpdateChecker.UpdateBaseFolder, "programs"), true); } } catch { success = false; } if (!success) { LogMessage("+ ERROR updating Automation Programs"); } return success; }
public List<string> DownloadAndUncompress(ReleaseInfo releaseInfo) { if (ArchiveDownloadUpdate != null) ArchiveDownloadUpdate(this, new ArchiveDownloadEventArgs(releaseInfo, ArchiveDownloadStatus.DOWNLOADING)); // string destinationFolder = Path.Combine(updateFolder, "files"); string archiveName = Path.Combine(updateFolder, "archives", "hg_update_" + releaseInfo.Version.Replace(" ", "_").Replace(".", "_") + ".zip"); if (!Directory.Exists(Path.GetDirectoryName(archiveName))) { Directory.CreateDirectory(Path.GetDirectoryName(archiveName)); } using (var client = new WebClientPx()) { client.Headers.Add("user-agent", "HomeGenieUpdater/1.0 (compatible; MSIE 7.0; Windows NT 6.0)"); try { client.DownloadFile(releaseInfo.DownloadUrl, archiveName); } catch (Exception) { if (ArchiveDownloadUpdate != null) ArchiveDownloadUpdate(this, new ArchiveDownloadEventArgs(releaseInfo, ArchiveDownloadStatus.ERROR)); return null; // throw; } finally { client.Dispose(); } } // Unarchive (unzip) if (ArchiveDownloadUpdate != null) ArchiveDownloadUpdate(this, new ArchiveDownloadEventArgs(releaseInfo, ArchiveDownloadStatus.DECOMPRESSING)); bool errorOccurred = false; var files = Utility.UncompressTgz(archiveName, destinationFolder); errorOccurred = (files.Count == 0); if (ArchiveDownloadUpdate != null) { if (errorOccurred) ArchiveDownloadUpdate(this, new ArchiveDownloadEventArgs(releaseInfo, ArchiveDownloadStatus.ERROR)); else ArchiveDownloadUpdate(this, new ArchiveDownloadEventArgs(releaseInfo, ArchiveDownloadStatus.COMPLETED)); } // update release_info.xml file with last releaseInfo ReleaseDate field in order to reflect github release date if (files.Contains(Path.Combine("homegenie", releaseFile))) { var ri = GetReleaseFile(Path.Combine(destinationFolder, "homegenie", releaseFile)); ri.ReleaseDate = releaseInfo.ReleaseDate.ToUniversalTime(); XmlSerializer serializer = new XmlSerializer(typeof(ReleaseInfo)); using (TextWriter writer = new StreamWriter(Path.Combine(destinationFolder, "homegenie", releaseFile))) { serializer.Serialize(writer, ri); } } return files; }