def OnBuildCreatePackage(self, stage, targetFile): Logger.Debug(__name__, GT(u'Creating {} from {}').format(targetFile, stage)) packager = GetExecutable(u'dpkg-deb') fakeroot = GetExecutable(u'fakeroot') if not fakeroot or not packager: return (dbrerrno.ENOENT, GT(u'Cannot run "fakeroot dpkg')) packager = os.path.basename(packager) Logger.Debug(__name__, GT(u'System packager: {}').format(packager)) # DEBUG: cmd = u'{} {} -b "{}" "{}"'.format(fakeroot, packager, stage, targetFile) Logger.Debug(__name__, GT(u'Executing: {}').format(cmd)) output = GetCommandOutput(fakeroot, ( packager, u'-b', stage, targetFile, )) Logger.Debug(__name__, GT(u'Build output: {}').format(output)) return output
def ExportDeprecated(self, outDir, outName=wx.EmptyString): if not os.path.isdir(outDir): Logger.Debug(__name__, u'Directory does not exist: {}'.format(outDir)) return ERR_DIR_NOT_AVAILABLE if outName == wx.EmptyString: outName = page_ids[self.GetId()].upper() page_info = self.Get() if not page_info: return 0 if not outName: outName = self.Name if TextIsEmpty(page_info): return 0 absolute_filename = u'{}/{}'.format(outDir, outName) Logger.Debug(outName, u'Exporting: {}'.format(absolute_filename)) WriteFile(absolute_filename, page_info) return 0
def InitMountItems(self): # Failsafe conditional in case of errors reading user home directory home_exists = os.path.isdir(PATH_home) if home_exists: home_item = self.AppendItem(self.root_item, GT(u'Home directory'), PATH_home, ImageList.GetImageIndex(u'folder-home'), expImage=ImageList.GetImageIndex(u'folder-home-open')) self.mount_list.append(home_item) # List storage devices currently mounted on system stdevs = GetMountedStorageDevices() for DEV in stdevs: # Do not re-add home directory in case it is mounted on its own partition if DEV.MountPoint == PATH_home: continue add_item = os.path.ismount(DEV.MountPoint) if add_item: for PITEM in self.mount_list: if DEV.MountPoint == PITEM.Path: add_item = False break if add_item: Logger.Debug(__name__, u'Adding new mount PathItem instance: {}'.format(DEV.Label)) self.mount_list.append(self.AppendItem(self.root_item, DEV.Label, DEV.MountPoint, ImageList.GetImageIndex(DEV.Type))) continue else: Logger.Debug(__name__, u'PathItem instance for "{}" directory already exists'.format(DEV.MountPoint))
def OnTimerStop(self, event=None): Logger.Debug(__name__, u'OnTimerStop') if not self.timer.IsRunning(): Logger.Debug(__name__, GT(u'Timer is stopped')) else: Logger.Debug(__name__, GT(u'Timer is running')) if self.build_error: error_lines = self.build_error[:-1] error_output = self.build_error[-1] ShowErrorDialog(error_lines, error_output, self) # Needs to be reset or error dialog will successively show self.build_error = None return msg_lines = ( GT(u'Quick build complete'), self.input_target.GetValue(), ) ShowMessageDialog(msg_lines, GT(u'Build Complete'), module=__name__)
def WriteMD5(stage_dir, parent=None): CMD_md5sum = GetExecutable(u'md5sum') # Show an error if the 'md5sum' command does not exist # This is only a failsafe & should never actually occur if not CMD_md5sum: if not parent: parent = GetMainWindow() md5_label = GetField(pgid.BUILD, chkid.MD5).GetLabel() err_msg1 = GT(u'The "md5sum" command was not found on the system.') err_msg2 = GT(u'Uncheck the "{}" box.').format(md5_label) err_msg3 = GT( u'Please report this error to one of the following addresses:') err_url1 = u'https://github.com/AntumDeluge/debreate/issues' err_url2 = u'https://sourceforge.net/p/debreate/bugs/' Logger.Error( __name__, u'{} {} {}\n\t{}\n\t{}'.format(err_msg1, err_msg2, err_msg3, err_url1, err_url2)) md5_error = ErrorDialog(parent, text=u'{}\n{}\n\n{}'.format( err_msg1, err_msg2, err_msg3)) md5_error.AddURL(err_url1) md5_error.AddURL(err_url2) md5_error.ShowModal() return None temp_list = [] md5_list = [] # Final list used to write the md5sum file for ROOT, DIRS, FILES in os.walk(stage_dir): # Ignore the 'DEBIAN' directory if os.path.basename(ROOT) == u'DEBIAN': continue for F in FILES: F = u'{}/{}'.format(ROOT, F) md5 = GetCommandOutput(CMD_md5sum, (u'-t', F)) Logger.Debug(__name__, u'WriteMD5: GetCommandOutput: {}'.format(md5)) temp_list.append(md5) for item in temp_list: # Remove [stage_dir] from the path name in the md5sum so that it has a # true unix path # e.g., instead of "/myfolder_temp/usr/local/bin", "/usr/local/bin" sum_split = item.split(u'{}/'.format(stage_dir)) sum_join = u''.join(sum_split) md5_list.append(sum_join) # Create the md5sums file in the "DEBIAN" directory return WriteFile(u'{}/DEBIAN/md5sums'.format(stage_dir), u'{}\n'.format(u'\n'.join(md5_list)))
def Export(self, out_dir, executable=True, build=False): if not os.path.isdir(out_dir): Logger.Error(__name__, GT(u'Directory not available: {}'.format(out_dir))) return (ERR_DIR_NOT_AVAILABLE, __name__) if build: absolute_filename = ConcatPaths((out_dir, self.FileName)) else: filename = u'{}-{}'.format(page_ids[self.Parent.GetId()].upper(), self.FileName) absolute_filename = ConcatPaths((out_dir, filename)) script_text = u'{}\n\n{}'.format(self.GetShebang(), self.ScriptBody.GetValue()) WriteFile(absolute_filename, script_text) if not os.path.isfile(absolute_filename): Logger.Error(__name__, GT(u'Could not write to file: {}'.format(absolute_filename))) return (ERR_FILE_WRITE, __name__) if executable: os.chmod(absolute_filename, 0755) return (0, None)
def OnMenuChangePage(self, event=None): page_id = None if event: page_id = event.GetId() Logger.Debug(__name__, GT(u'Page ID from menu event: {}').format(page_id)) else: for M in self.GetMenu(menuid.PAGE).GetMenuItems(): if M.IsChecked(): page_id = M.GetId() Logger.Debug( __name__, GT(u'Page ID from menu item: {}').format(page_id)) break if page_id == None: Logger.Error(__name__, GT(u'Could not get page ID')) return self.Wizard.ShowPage(page_id)
def ProjectSaveAs(self): wildcards = ( u'{} (.{})'.format(GT(u'Debreate project files'), PROJECT_ext), u'*.{}'.format(PROJECT_ext), ) save_dialog = GetFileSaveDialog(self, GT(u'Save Debreate Project'), wildcards, PROJECT_ext) if ShowDialog(save_dialog): project_path = save_dialog.GetPath() project_filename = save_dialog.GetFilename() Logger.Debug(__name__, GT(u'Project save path: {}').format(project_path)) Logger.Debug( __name__, GT(u'Project save filename: {}').format(project_filename)) saved = self.ProjectSave(project_path) if saved == dbrerrno.SUCCESS: self.ProjectSetDirty(False) return saved Logger.Debug(__name__, GT(u'Not saving project')) return dbrerrno.ECNCLD
def DeleteAllItems(self): if ListCtrl.DeleteAllItems(self): self.FileItems = [] else: Logger.Warn(__name__, u'Failed to delete all items from FileList') Logger.Debug(__name__, u'Visual item count: {}'.format(self.GetItemCount())) Logger.Debug(__name__, u'Acutal item count: {}'.format(len(self.FileItems)))
def ImportExes(self, event=None): event_id = event.GetId() if event_id == btnid.IMPORT: # First clear the Auto-Link display and the executable list self.Executables.Reset() # Get executables from "files" tab file_list = GetField(pgid.FILES, inputid.LIST) for INDEX in range(file_list.GetItemCount()): # Get the filename from the source file_name = file_list.GetFilename(INDEX, basename=True) file_path = file_list.GetPath(INDEX) # Where the file linked to will be installed file_target = file_list.GetItem(INDEX, 1) # Walk directory to find executables if file_list.IsDirectory(INDEX): for EXE in GetFiles(file_path, os.X_OK): self.Executables.Append(FileItem(EXE, file_target)) # Search for executables (distinguished by red text) elif file_list.IsExecutable(INDEX): try: # If destination doesn't start with "/" do not include executable if file_target.GetText()[0] == u'/': if file_target.GetText()[-1] == u'/' or file_target.GetText()[-1] == u' ': # In case the full path of the destination is "/" keep going if len(file_target.GetText()) == 1: dest_path = u'' else: search = True # Set the number of spaces to remove from dest path in case of multiple "/" slashes = 1 while search: # Find the number of slashes/spaces at the end of the filename endline = slashes - 1 if file_target.GetText()[-slashes] == u'/' or file_target.GetText()[-slashes] == u' ': slashes += 1 else: dest_path = file_target.GetText()[:-endline] search = False else: dest_path = file_target.GetText() self.Executables.Append(file_name, dest_path) else: Logger.Warn(__name__, u'{}: The executables destination is not valid'.format(__name__)) except IndexError: Logger.Warn(__name__, u'{}: The executables destination is not available'.format(__name__)) elif event_id in (btnid.REMOVE, wx.WXK_DELETE): self.Executables.RemoveSelected()
def ShowLog(self): self.RefreshLog() self.Show(True) if not self.LogPollThread.IsActive(): Logger.Debug(__name__, u'Starting log polling thread ...') self.LogPollThread.Start() else: Logger.Debug(__name__, u'Log polling thread is already started')
def Delete(self, item): item = self.GetIndex(item) filename = self.GetPath(item) if self.DeleteItem(item): self.FileItems.pop(item) Logger.Debug(__name__, u'Deleted item from BasicFileList: {}'.format(filename)) return True Logger.Warn(__name__, u'Failed to deleted item from BasicFilelist: {}'.format(filename)) return False
def __init__(self, parent, title=u'Choose a file', defaultDir=None, defaultFile=u'', defaultExt=None, wildcard=wx.FileSelectorDefaultWildcardStr, style=wx.FD_DEFAULT_STYLE, pos=wx.DefaultPosition, size=wx.DefaultSize, name=u'filedlg'): if not defaultDir: defaultDir = os.getcwd() # Setting os.getcwd() causes dialog to always be opened in working directory wx.FileDialog.__init__(self, parent, title, defaultDir, defaultFile, wildcard, style, pos) self.SetSize(size) self.SetName(name) self.Extension = defaultExt if self.WindowStyleFlag & wx.FD_SAVE: wx.EVT_BUTTON(self, self.AffirmativeId, self.OnAccept) if self.WindowStyleFlag & wx.FD_CHANGE_DIR: Logger.Warn( __name__, u'Found FD_CHANGE_DIR style, could conflict with OnAccept method' ) self.CenterOnParent()
def IsOkay(self): Logger.Warn( __name__, GT(u'Page {} does not override inherited method IsOkay').format( self.GetName())) return False
def ShowMessageDialog(text, title=GT(u'Message'), details=None, module=None, parent=None, linewrap=0): if not parent: parent = GetMainWindow() logger_text = text if isinstance(text, (tuple, list)): logger_text = u'; '.join(text) text = u'\n'.join(text) if details: logger_text = u'{}:\n{}'.format(logger_text, details) message_dialog = DetailedMessageDialog(parent, title, ICON_INFORMATION, text, linewrap=linewrap) if details: message_dialog.SetDetails(details) Logger.Debug(module, logger_text) message_dialog.ShowModal()
def OnProjectNew(self, event=None): Logger.Debug( __name__, GT(u'Project loaded before OnProjectNew: {}').format( self.ProjectIsLoaded())) return self.ProjectClose()
def ShowLogWindow(self, show=True): Logger.Debug(__name__, GT(u'Show log window: {}').format(show)) self.log_window.Show(show) if self.menu_debug.IsChecked(menuid.DEBUG) != show: self.menu_debug.Check(menuid.DEBUG, show)
def ProjectOpenLegacy(self, data, filename): Logger.Debug(__name__, GT(u'Legacy project format (text) detected')) def ProjectError(): wx.MessageDialog(self, GT(u'Not a valid Debreate project'), GT(u'Error'), style=wx.OK | wx.ICON_ERROR).ShowModal() if data == wx.EmptyString: ProjectError() return dbrerrno.EBADFT lines = data.split(u'\n') app = lines[0].split(u'-')[0].split(u'[')[1] if app != u'DEBREATE': ProjectError() return dbrerrno.EBADFT # *** Get Control Data *** # control_data = data.split(u'<<CTRL>>\n')[1].split(u'\n<</CTRL>>')[0] depends_data = self.Wizard.GetPage(pgid.CONTROL).Set(control_data) self.Wizard.GetPage(pgid.DEPENDS).Set(depends_data) # *** Get Files Data *** # files_data = data.split(u'<<FILES>>\n')[1].split(u'\n<</FILES>>')[0] self.Wizard.GetPage(pgid.FILES).Set(files_data) # *** Get Scripts Data *** # scripts_data = data.split(u'<<SCRIPTS>>\n')[1].split( u'\n<</SCRIPTS>>')[0] self.Wizard.GetPage(pgid.SCRIPTS).Set(scripts_data) # *** Get Changelog Data *** # clog_data = data.split(u'<<CHANGELOG>>\n')[1].split( u'\n<</CHANGELOG>>')[0] self.Wizard.GetPage(pgid.CHANGELOG).Set(clog_data) # *** Get Copyright Data *** # try: cpright_data = data.split(u'<<COPYRIGHT>>\n')[1].split( u'\n<</COPYRIGHT')[0] self.Wizard.GetPage(pgid.COPYRIGHT).Set(cpright_data) except IndexError: pass # *** Get Menu Data *** # m_data = data.split(u'<<MENU>>\n')[1].split(u'\n<</MENU>>')[0] self.Wizard.GetPage(pgid.LAUNCHERS).Set(m_data) # Get Build Data build_data = data.split(u'<<BUILD>>\n')[1].split(u'\n<</BUILD')[0] self.Wizard.GetPage(pgid.BUILD).Set(build_data) self.ProjectSetDirty(False) # Legacy projects should return None since we can't save in that format return None
def __init__(self, cfgKey=None, cfgSect=None): self.ConfigKey = cfgKey self.ConfigSection = cfgSect if not self.ConfigSection: self.ConfigSection = u'GENERAL' if self.ConfigKey == None: self.ConfigKey = self.GetName() # Add to recognized configuration keys SetDefaultConfigKey(self.ConfigKey, self.GetDefaultValue()) # Set state using config file if found state = ReadConfig(self.ConfigKey) ret_codes = ( ConfCode.FILE_NOT_FOUND, ConfCode.KEY_NOT_DEFINED, ConfCode.KEY_NO_EXIST, ) # FIXME: if state not in (ret_codes): self.SetValue(state) else: Logger.Debug(__name__, u'Key not found: {}'.format(self.ConfigKey)) # *** Event Handling *** # if isinstance(self, wx.CheckBox): self.Bind(wx.EVT_CHECKBOX, self.OnToggle)
def GetPage(self, pageId): for P in self.Pages: if P.GetId() == pageId: return P Logger.Warn(__name__, u'Page with ID {} has not been constructed'.format(pageId))
def LaunchFirstRun(debreate_app): FR_dialog = FirstRun() debreate_app.SetTopWindow(FR_dialog) FR_dialog.ShowModal() init_conf_code = InitializeConfig() Logger.Debug( __name__, u'Configuration initialized: {}'.format( init_conf_code == ConfCode.SUCCESS)) if (init_conf_code != ConfCode.SUCCESS) or (not os.path.isfile(default_config)): msg_l1 = GT( u'An error occurred trying to create the configuration file:') msg_l2 = GT(u'Please report this error to Debreate\'s developers') ShowErrorDialog(u'{} {}\n\n{}'.format(msg_l1, default_config, msg_l2)) return init_conf_code FR_dialog.Destroy() # Delete first run dialog from memory del (FR_dialog) return init_conf_code
def InitPage(self): Logger.Debug( __name__, GT(u'Page {} does not override inherited method InitPage').format( self.GetName())) return False
def ExportBuild(self, target): Logger.Warn( __name__, GT(u'Page {} does not override inherited method ExportBuild'). format(self.GetName())) return (dbrerrno.SUCCESS, None)
def OnAccept(self, event=None): if self.IsSaveDialog(): if self.Extension: if not self.Filename.endswith(self.Extension): # Adds extensions if not specified self.SetFilename(self.Filename) if self.Path: if os.path.isfile(self.Path): overwrite = OverwriteDialog(self, self.Path) if not ShowDialog(overwrite): return try: os.remove(self.Path) except OSError: # File was removed before confirmation Logger.Debug( __name__, u'Item was removed before confirmation: {}'.format( self.Path)) # Because we are not using default FileDialog methods, we must set # directory manually. self.SetDirectory(os.path.dirname(self.Path)) # File & directory dialogs should call this function ChangeWorkingDirectory(self.GetDirectory()) self.EndModal(self.AffirmativeId)
def OnExportLauncher(self, event=None): Logger.Debug(__name__, u'Export launcher ...') export = GetFileSaveDialog(GetMainWindow(), GT(u'Save Launcher')) if ShowDialog(export): target = export.GetPath() # Create a backup file # FIXME: Create backup files in WriteFile function? overwrite = False if os.path.isfile(target): backup = u'{}.backup'.format(target) shutil.copy(target, backup) overwrite = True try: self.ExportToFile(target) if overwrite: os.remove(backup) except UnicodeEncodeError: detail1 = GT( u'Unfortunately Debreate does not support unicode yet.') detail2 = GT( u'Remove any non-ASCII characters from your project.') ShowErrorDialog(GT(u'Save failed'), u'{}\n{}'.format(detail1, detail2), title=GT(u'Unicode Error')) os.remove(target) # Restore from backup shutil.move(backup, target)
def GetIdLabel(self, pageId): if pageId in self.Labels: return self.Labels[pageId] Logger.Warn(__name__, u'Label for ID {} not found'.format(pageId)) return wx.EmptyString
def AddFile(self, filename, sourceDir, targetDir=None, executable=False): list_index = self.GetItemCount() # Method can be called with two argements: absolute filename & target directory if targetDir == None: targetDir = sourceDir sourceDir = os.path.dirname(filename) filename = os.path.basename(filename) source_path = ConcatPaths((sourceDir, filename)) Logger.Debug(__name__, GT(u'Adding file: {}').format(source_path)) self.InsertStringItem(list_index, filename) self.SetStringItem(list_index, columns.SOURCE, sourceDir) self.SetStringItem(list_index, columns.TARGET, targetDir) self.SetStringItem(list_index, columns.TYPE, GetFileMimeType(source_path)) if os.path.isdir(source_path): self.SetItemTextColour(list_index, self.FOLDER_TEXT_COLOR) else: # TODO: Use 'GetFileMimeType' module to determine file type if os.access(source_path, os.X_OK) or executable: self.SetFileExecutable(list_index) if not os.path.isfile(source_path): self.SetItemBackgroundColour(list_index, COLOR_warn) # File was added but does not exist on filesystem return False return True
def ParseMountedDevices(): # FIXME: Identify labels for different systems & drive types device_labels = ( u'/dev/sd', ) # Empty the device list mounted_devices = {} if os.path.isfile(u'/etc/mtab'): mtab = ReadFile(u'/etc/mtab', split=True, convert=list) # Only keep lines referring to devices directory for X in reversed(range(len(mtab))): if not mtab[X].startswith(u'/dev'): mtab.pop(X) mtab.sort() for LINE in mtab: LINE = LINE.split(u' ') device = LINE[0] mount_point = LINE[1] for LABEL in device_labels: if device.startswith(LABEL): mounted_devices[device] = mount_point else: Logger.Warn(__name__, u'/etc/mtab file does not exist. Mounted devices list will be empty') return mounted_devices
def OnWizardBtnPage(self, event=None): #@UnusedVariable ID = self.Wizard.GetCurrentPageId() Logger.Debug(__name__, GT(u'Event: EVT_CHANGE_PAGE, Page ID: {}').format(ID)) menu_page = self.GetMenu(menuid.PAGE) if not menu_page.IsChecked(ID): menu_page.Check(ID, True)
def InstallPackage(self, package): system_installer = GetSystemInstaller() if not system_installer: ShowErrorDialog( GT(u'Cannot install package'), GT(u'A compatible package manager could not be found on the system' ), __name__, warn=True) return Logger.Info(__name__, GT(u'Attempting to install package: {}').format(package)) Logger.Info(__name__, GT(u'Installing with {}').format(system_installer)) install_cmd = ( system_installer, package, ) wx.Yield() # FIXME: Use ExecuteCommand here install_output = subprocess.Popen(install_cmd) # Command appears to not have been executed correctly if install_output == None: ShowErrorDialog(GT(u'Could not install package: {}'), GT(u'An unknown error occurred'), __name__) return # Command executed but did not return success code if install_output.returncode: err_details = ( GT(u'Process returned code {}').format( install_output.returncode), GT(u'Command executed: {}').format(u' '.join(install_cmd)), ) ShowErrorDialog(GT(u'An error occurred during installation'), u'\n'.join(err_details), __name__) return