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 OnHelp(self, event=None): #@UnusedVariable if u'alpha' in GetTestList(): HelpDialog(self).ShowModal() else: # FIXME: files should be re-cached when Debreate upgraded to new version # TODO: trim unneeded text cached = False manual_cache = ConcatPaths(PATH_cache, u'manual') manual_index = ConcatPaths(manual_cache, u'index.html') if not os.path.isdir(manual_cache): os.makedirs(manual_cache) elif os.path.isfile(manual_index): cached = True url_manual = u'https://debreate.wordpress.com/manual/' # NOTE: use urllib.request.urlopen for Python 3 manual_data = urllib.urlopen(url_manual) url_state = manual_data.getcode() if url_state == 200: # cache files if not cached: self.progress = ProgressDialog( self, message=GT(u'Caching manual files'), style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE) self.Disable() self.timer.Start(100) Thread(self.__cacheManualFiles, ( url_manual, manual_cache, manual_index, )).Start() self.progress.ShowModal() manual_dialog = wx.Dialog(self, title=u'Debreate Manual', size=(800, 500), style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) manual = wx.html.HtmlWindow(manual_dialog) wx.Yield() if manual.LoadFile(manual_index): manual_dialog.CenterOnParent() manual_dialog.ShowModal() else: wx.Yield() webbrowser.open(url_manual) manual_dialog.Destroy() else: # open local document wx.Yield() subprocess.call( [u'xdg-open', u'{}/docs/usage.pdf'.format(PATH_app)])
def GetSaveData(self): file_list = [] item_count = self.lst_files.GetItemCount() if item_count > 0: count = 0 while count < item_count: filename = self.lst_files.GetItemText(count) source = self.lst_files.GetItem(count, columns.SOURCE).GetText() target = self.lst_files.GetItem(count, columns.TARGET).GetText() absolute_filename = ConcatPaths((source, filename)) # Populate list with tuples of ('src', 'file', 'dest') if self.lst_files.GetItemTextColour(count) == (255, 0, 0): # Mark file as executable file_list.append((u'{}*'.format(absolute_filename), filename, target)) else: file_list.append((absolute_filename, filename, target)) count += 1 return_list = [] for F in file_list: f0 = u'{}'.encode(u'utf-8').format(F[0]) f1 = u'{}'.encode(u'utf-8').format(F[1]) f2 = u'{}'.encode(u'utf-8').format(F[2]) return_list.append(u'{} -> {} -> {}'.format(f0, f1, f2)) return u'<<FILES>>\n1\n{}\n<</FILES>>'.format(u'\n'.join(return_list)) else: # Place a "0" in FILES field if we are not saving any files return u'<<FILES>>\n0\n<</FILES>>'
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 GetBitmap(name, size=16, cat=None, img_type=u'png'): image_path = GetImagePath(name, size, cat, img_type) if not image_path: #return wx.NullBitmap return wx.Bitmap(ConcatPaths((PATH_bitmaps, u'24', u'failsafe.png'))) return wx.Bitmap(image_path, wx.BITMAP_TYPE_PNG)
def Expand(self, item): if isinstance(item, PathItem): if item.IsFile(): return False dirs = [] files = [] if not self.ItemHasChildren(item): # FIXME: Should use regular expressions for filter item_path = item.GetPath() try: for LABEL in os.listdir(item_path): # Ignore filtered items filtered = False for FILTER in self.exclude_pattern: if LABEL.startswith(FILTER): filtered = True break if not filtered: child_path = ConcatPaths((item_path, LABEL)) if os.path.isdir(child_path) and os.access(child_path, os.R_OK): dirs.append((LABEL, child_path,)) elif os.path.isfile(child_path) and os.access(child_path, os.R_OK): files.append((LABEL, child_path,)) # Sort directories first for DIR, PATH in sorted(dirs): child = self.AppendItem(item, DIR, PATH) self.SetItemImage(child, ImageList.GetImageIndex(u'folder'), wx.TreeItemIcon_Normal) self.SetItemImage(child, ImageList.GetImageIndex(u'folder-open'), wx.TreeItemIcon_Expanded) item.AddChild(child) for FILE, PATH in sorted(files): child = self.AppendItem(item, FILE, PATH) self.SetItemImage(child, child.ImageIndex, wx.TreeItemIcon_Normal) item.AddChild(child) except OSError: Logger.Warn(__name__, u'No such file or directory: {}'.format(item_path)) # Recursively expand parent items parent = self.GetItemParent(item) if parent: self.Expand(parent) if isinstance(item, PathItem): item = item.GetBaseItem() return wx.TreeCtrl.Expand(self, item)
def OnBuildMD5Sum(self, stage): Logger.Debug(__name__, GT(u'Creating MD5sum file in {}').format(stage)) WriteMD5(stage) return GT(u'md5sums file created: {}'.format( os.path.isfile(ConcatPaths(( stage, u'DEBIAN/md5sums', )))))
def CreateButton(parent, btnId=wx.ID_ANY, label=wx.EmptyString, image=None, size=32, tooltip=None, name=None, commands=None, requireAll=False): if not image: image = btnid.GetImage(btnId) # Use titleized version of the image name for the label if not label and image: label = image.title() if not name: name = label button = None if image: image = ConcatPaths( (PATH_bitmaps, u'button', GS(size), u'{}.png'.format(image))) if not os.path.isfile(image): Logger.Warn( __name__, u'CreateButton: Attempted to set not-existent image for button (ID {}):' .format(btnId), details=image) else: button = CustomButton(parent, image, btnId, name=name, commands=commands, requireAll=requireAll) if not tooltip: tooltip = label button.SetToolTipString(tooltip) # Use a standard button if not button: button = Button(parent, btnId, label, name=name, commands=commands, requireAll=requireAll) return button
def GetImagePath(name, size=16, cat=None, img_type=u'png'): name = u'{}.{}'.format(name, img_type) if cat: paths = (PATH_bitmaps, cat, GS(size), name) else: paths = (PATH_bitmaps, GS(size), name) image_path = ConcatPaths(paths) # Attempt to use failsafe image if file does not exists if not os.path.isfile(image_path): image_path = ConcatPaths((PATH_bitmaps, GS(size), u'failsafe.png')) # Last resort is to retrun None if a failsafe image was not found if not os.path.isfile(image_path): return None return image_path
def GetLicenseTemplateFile(l_name): template_path = None # Check local templates first if l_name in GetFiles(local_licenses_path): template_path = ConcatPaths((local_licenses_path, l_name)) elif l_name in GetFiles(app_licenses_path): template_path = ConcatPaths((app_licenses_path, l_name)) elif l_name in GetFiles(sys_licenses_path): template_path = ConcatPaths((sys_licenses_path, l_name)) if not template_path or not os.path.isfile(template_path): Logger.Warn(__name__, GT(u'License template not found: {}'.format(template_path))) return Logger.Debug(__name__, GT(u'Loading license template: {}'.format(template_path))) return template_path
def ExportBuild(self, stage): target = self.pnl_target.GetPath() if target == self.pnl_target.GetDefaultPath(): target.replace(u'<package>', GetFieldValue(pgid.CONTROL, inputid.PACKAGE)) stage = ConcatPaths((stage, target)) if not os.path.isdir(stage): os.makedirs(stage) # FIXME: Allow user to set filename self.Export(stage, u'changelog', True) export_summary = GT(u'Changelog export failed') changelog = ConcatPaths((stage, u'changelog.gz')) if os.path.isfile(changelog): export_summary = GT(u'Changelog export to: {}').format(changelog) return (0, export_summary)
def GetFiles(path, flag=None): file_list = [] for PATH, DIRS, FILES in os.walk(path): for F in FILES: file_path = ConcatPaths((path, F)) if os.path.isfile(file_path): # Don't add files that do not match 'flag' attributes if flag: if not os.access(file_path, flag): continue file_list.append(F) return sorted(file_list, key=GS.lower)
def OnEndLabelEdit(self, event=None): if event: if event.IsEditCancelled(): Logger.Debug(__name__, u'Vetoing due to cancelled edit') event.Veto() return item = event.GetItem() for I in self.item_list: if I.GetBaseItem() == item: item = I break new_label = event.GetLabel() item_dir = os.path.dirname(item.Path) new_path = ConcatPaths((item_dir, new_label)) try: if os.path.exists(new_path): msg_l1 = GT(u'Name already exists:') ShowErrorDialog(u'{}\n\n{}'.format(msg_l1, new_path)) event.Veto() return os.rename(item.Path, new_path) ## ???: Another way to test if rename was successful? if os.path.exists(new_path): # Items path must be updated I.Path = new_path except OSError: Logger.Debug( __name__, u'Item not renamed, traceback details below:\n\n{}'.format( traceback.format_exc())) event.Veto() Logger.Debug(__name__, u'New item path: {}'.format(item.Path))
def ExportBuild(self, target, installedSize=0): self.Export(target, u'control') absolute_filename = ConcatPaths((target, u'control')) if not os.path.isfile(absolute_filename): return GT(u'Control file was not created') if installedSize: control_data = ReadFile(absolute_filename, split=True, convert=list) size_line = u'Installed-Size: {}'.format(installedSize) if len(control_data) > 3: control_data.insert(3, size_line) else: control_data.append(size_line) # Be sure not to strip trailing newline (dpkg is picky) WriteFile(absolute_filename, control_data, noStrip=u'\n') return GT(u'Control file created: {}').format(absolute_filename)
# *** Application information *** # ## Debreate's main homepage APP_homepage = u'https://antumdeluge.github.io/debreate-web/' ## The old SF homepage APP_homepage_sf = u'http://debreate.sourceforge.net/' ## GitHub project page APP_project_gh = u'https://github.com/AntumDeluge/debreate' ## Sourceforge project page APP_project_sf = u'https://sourceforge.net/projects/debreate' ## Application's logo APP_logo = wx.Icon(ConcatPaths((PATH_bitmaps, u'icon/64/logo.png')), wx.BITMAP_TYPE_PNG) ## Name of application APP_name = u'Debreate' # *** Version information *** # VERSION_maj = 0 VERSION_min = 8 VERSION_rel = 0 VERSION_tuple = (VERSION_maj, VERSION_min, VERSION_rel) VERSION_string = u'{}.{}.{}'.format(VERSION_maj, VERSION_min, VERSION_rel) # Development version: Increment for every development release VERSION_dev = 1
def OnBuild(self, event=None): stage = self.input_stage.GetValue() target = self.input_target.GetValue().rstrip(u'/') # Attempt to use DEBIAN/control file to set output filename. This is normally # done automatically by the dpkg command, but we need to set it manually to # check for overwriting a file. if os.path.isdir(target): control_file = ConcatPaths((stage, u'DEBIAN/control')) if os.path.isfile(control_file): control_lines = ReadFile(control_file, split=True) name = None version = None arch = None for LINE in control_lines: if LINE.startswith(u'Package:'): name = LINE.replace(u'Package: ', u'').strip() elif LINE.startswith(u'Version:'): version = LINE.replace(u'Version: ', u'').strip() elif LINE.startswith(u'Architecture:'): arch = LINE.replace(u'Architecture: ', u'').strip() if name and version and arch: target = ConcatPaths((target, u'{}.deb'.format(u'_'.join(( name, version, arch, ))))) # Automatically add .deb filename extension if not present elif not target.lower().endswith(u'.deb'): target = u'{}.deb'.format(target) if not os.path.isdir(stage): ShowErrorDialog(GT(u'Stage directory does not exist'), stage, self, True) return target_path = os.path.dirname(target) if not os.path.isdir(target_path): ShowErrorDialog(GT(u'Target directory does not exist'), target_path, self, True) return elif not os.access(target_path, os.W_OK): ShowErrorDialog(GT(u'No write access to target directory'), target_path, self, True) return # Update the text input if target altered if target != self.input_target.GetValue(): self.input_target.SetValue(target) # Check for pre-existing file if os.path.isfile(target): if not OverwriteDialog(self, target).Confirmed(): return self.SetTitle(u'{} ({})'.format(self.title, GT(u'in progress'))) # Don't allow dialog to be closed while build in progress self.Disable() self.timer.Start(100) # Start new thread for background process Thread(self.Build, stage, target).Start()
def __init__(self, node, mount_point): self.Node = node self.MountPoint = mount_point self.Label = None label_dir = u'/dev/disk/by-label' if os.path.isdir(label_dir): for LABEL in os.listdir(label_dir): link = ConcatPaths((label_dir, LABEL)) if os.path.islink(link): link_node = os.path.realpath(link) if link_node == self.Node: Logger.Debug(__name__, u'Found label for {}: {}'.format(self.Node, LABEL)) self.Label = LABEL break # As last resort just use mount point basename if not self.Label: if mount_point == u'/': self.Label = mount_point else: self.Label = os.path.basename(mount_point) device_types = { u'/dev/sd': u'drive-fixed', u'/dev/hd': u'drive-fixed', u'/dev/pd': u'drive-fixed', u'/dev/fd': u'drive-floppy', } # The type string is used in ui.tree.DirectroyTree to set item icon self.Type = None for TYPE in device_types: if node.startswith(TYPE): self.Type = device_types[TYPE] break # Extended device type check # ???: Better method? type_dir = u'/dev/disk/by-path' if os.path.isdir(type_dir): node_types = os.listdir(type_dir) for TYPE in node_types: link = ConcatPaths((type_dir, TYPE)) if os.path.islink(link): link_node = os.path.realpath(link) if link_node == self.Node: # Ensure we are only dealing with lowercase TYPE = TYPE.lower() if u'usb' in TYPE.split(u'-'): Logger.Debug(__name__, u'{} is a removable drive'.format(self.Node)) self.Type = u'removable'
def OnBuild(self, event=None): stage = self.input_stage.GetValue() target = self.input_target.GetValue().rstrip(u'/') # Attempt to use DEBIAN/control file to set output filename. This is normally # done automatically by the dpkg command, but we need to set it manually to # check for overwriting a file. if os.path.isdir(target): control_file = ConcatPaths((stage, u'DEBIAN/control')) if os.path.isfile(control_file): control_lines = ReadFile(control_file, split=True) name = None version = None arch = None for LINE in control_lines: if LINE.startswith(u'Package:'): name = LINE.replace(u'Package: ', u'').strip() elif LINE.startswith(u'Version:'): version = LINE.replace(u'Version: ', u'').strip() elif LINE.startswith(u'Architecture:'): arch = LINE.replace(u'Architecture: ', u'').strip() if name and version and arch: target = ConcatPaths((target, u'{}.deb'.format(u'_'.join((name, version, arch,))))) # Automatically add .deb filename extension if not present elif not target.lower().endswith(u'.deb'): target = u'{}.deb'.format(target) if not os.path.isdir(stage): ShowErrorDialog(GT(u'Stage directory does not exist'), stage, self, True) return target_path = os.path.dirname(target) if not os.path.isdir(target_path): ShowErrorDialog(GT(u'Target directory does not exist'), target_path, self, True) return elif not os.access(target_path, os.W_OK): ShowErrorDialog(GT(u'No write access to target directory'), target_path, self, True) return # Update the text input if target altered if target != self.input_target.GetValue(): self.input_target.SetValue(target) # Check for pre-existing file if os.path.isfile(target): if not OverwriteDialog(self, target).Confirmed(): return self.SetTitle(u'{} ({})'.format(self.title, GT(u'in progress'))) # Don't allow dialog to be closed while build in progress self.Disable() self.timer.Start(100) # Start new thread for background process Thread(self.Build, stage, target).Start()
compile_dirs = ( u'dbr', u'globals', u'wizbin', ) if not os.access(PATH_app, os.W_OK): print(u'ERROR: No write privileges for {}'.format(PATH_app)) sys.exit(errno.EACCES) print(u'Compiling Python modules (.py) to bytecode (.pyc) ...\n') print(u'Compiling root directory: {}'.format(PATH_app)) for F in os.listdir(PATH_app): if os.path.isfile(F) and F.endswith(u'.py') and F != u'init.py': F = ConcatPaths((PATH_app, F)) compileall.compile_file(F) print for D in os.listdir(PATH_app): D = ConcatPaths((PATH_app, D)) if os.path.isdir(D) and os.path.basename(D) in compile_dirs: print(u'Compiling directory: {}'.format(D)) compileall.compile_dir(D) print sys.exit(0) if u'clean' in parsed_commands: import errno
def GetPath(self, index): file_dir = self.GetItemText(index, columns.SOURCE) file_name = self.GetItemText(index, columns.FILENAME) return ConcatPaths((file_dir, file_name))
from globals.paths import ConcatPaths from globals.paths import PATH_app from globals.paths import PATH_local from globals.strings import GS ## System common licenses sys_licenses_path = u'/usr/share/common-licenses' ## Application templates # # Path to application templates stored in the system Debreate directory. # <PATH_app>/templates # FIXME: Should be stored elsewhere? /etc? /lib? app_templates_path = ConcatPaths((PATH_app, u'templates')) ## Application licenses # # Path to license templates stored in the Debreate data directory # FIXME: Rename to 'global_licenses_path' # <PATH_app>/templates/li app_licenses_path = ConcatPaths((app_templates_path, u'licenses')) ## Local templates directory # # <PATH_local>/templates local_templates_path = ConcatPaths((PATH_local, u'templates')) ## License templates directory #
def Build(self, task_list, build_path, filename): # Declare this here in case of error before progress dialog created build_progress = None try: # Other mandatory tasks that will be processed mandatory_tasks = ( u'stage', u'install_size', u'control', u'build', ) # Add other mandatory tasks for T in mandatory_tasks: task_list[T] = None task_count = len(task_list) # Add each file for updating progress dialog if u'files' in task_list: task_count += len(task_list[u'files']) # Add each script for updating progress dialog if u'scripts' in task_list: task_count += len(task_list[u'scripts']) if DebugEnabled(): task_msg = GT(u'Total tasks: {}').format(task_count) print(u'DEBUG: [{}] {}'.format(__name__, task_msg)) for T in task_list: print(u'\t{}'.format(T)) create_changelog = u'changelog' in task_list create_copyright = u'copyright' in task_list pg_control = GetPage(pgid.CONTROL) pg_menu = GetPage(pgid.MENU) stage_dir = u'{}/{}__dbp__'.format(build_path, filename) if os.path.isdir(u'{}/DEBIAN'.format(stage_dir)): try: shutil.rmtree(stage_dir) except OSError: ShowErrorDialog( GT(u'Could not free stage directory: {}').format( stage_dir), title=GT(u'Cannot Continue')) return (dbrerrno.EEXIST, None) # Actual path to new .deb deb = u'"{}/{}.deb"'.format(build_path, filename) progress = 0 task_msg = GT(u'Preparing build tree') Logger.Debug(__name__, task_msg) wx.Yield() build_progress = ProgressDialog( GetMainWindow(), GT(u'Building'), task_msg, maximum=task_count, style=PD_DEFAULT_STYLE | wx.PD_ELAPSED_TIME | wx.PD_ESTIMATED_TIME | wx.PD_CAN_ABORT) DIR_debian = ConcatPaths((stage_dir, u'DEBIAN')) # Make a fresh build tree os.makedirs(DIR_debian) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) def UpdateProgress(current_task, message=None): task_eval = u'{} / {}'.format(current_task, task_count) if message: Logger.Debug(__name__, u'{} ({})'.format(message, task_eval)) wx.Yield() build_progress.Update(current_task, message) return wx.Yield() build_progress.Update(current_task) # *** Files *** # if u'files' in task_list: UpdateProgress(progress, GT(u'Copying files')) no_follow_link = GetField(GetPage(pgid.FILES), chkid.SYMLINK).IsChecked() # TODO: move this into a file functions module def _copy(f_src, f_tgt, exe=False): # NOTE: Python 3 appears to have follow_symlinks option for shutil.copy # FIXME: copying nested symbolic link may not work if os.path.isdir(f_src): if os.path.islink(f_src) and no_follow_link: Logger.Debug( __name__, u'Adding directory symbolic link to stage: {}'. format(f_tgt)) os.symlink(os.readlink(f_src), f_tgt) else: Logger.Debug( __name__, u'Adding directory to stage: {}'.format(f_tgt)) shutil.copytree(f_src, f_tgt) os.chmod(f_tgt, 0o0755) elif os.path.isfile(f_src): if os.path.islink(f_src) and no_follow_link: Logger.Debug( __name__, u'Adding file symbolic link to stage: {}'. format(f_tgt)) os.symlink(os.readlink(f_src), f_tgt) else: if exe: Logger.Debug( __name__, u'Adding executable to stage: {}'.format( f_tgt)) else: Logger.Debug( __name__, u'Adding file to stage: {}'.format(f_tgt)) shutil.copy(f_src, f_tgt) # Set FILE permissions if exe: os.chmod(f_tgt, 0o0755) else: os.chmod(f_tgt, 0o0644) files_data = task_list[u'files'] for FILE in files_data: file_defs = FILE.split(u' -> ') source_file = file_defs[0] target_file = u'{}{}/{}'.format(stage_dir, file_defs[2], file_defs[1]) target_dir = os.path.dirname(target_file) if not os.path.isdir(target_dir): os.makedirs(target_dir) # Remove asteriks from exectuables exe = False if source_file[-1] == u'*': exe = True source_file = source_file[:-1] _copy( source_file, u'{}/{}'.format(target_dir, os.path.basename(source_file)), exe) # Individual files progress += 1 UpdateProgress(progress) # Entire file task progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Strip files ***# # FIXME: Needs only be run if 'files' step is used if u'strip' in task_list: UpdateProgress(progress, GT(u'Stripping binaries')) for ROOT, DIRS, FILES in os.walk(stage_dir): #@UnusedVariable for F in FILES: # Don't check files in DEBIAN directory if ROOT != DIR_debian: F = ConcatPaths((ROOT, F)) if FileUnstripped(F): Logger.Debug(__name__, u'Unstripped file: {}'.format(F)) # FIXME: Strip command should be set as class member? ExecuteCommand(GetExecutable(u'strip'), F) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) package = GetField(pg_control, inputid.PACKAGE).GetValue() # Make sure that the directory is available in which to place documentation if create_changelog or create_copyright: doc_dir = u'{}/usr/share/doc/{}'.format(stage_dir, package) if not os.path.isdir(doc_dir): os.makedirs(doc_dir) # *** Changelog *** # if create_changelog: UpdateProgress(progress, GT(u'Creating changelog')) # If changelog will be installed to default directory changelog_target = task_list[u'changelog'][0] if changelog_target == u'STANDARD': changelog_target = ConcatPaths( (u'{}/usr/share/doc'.format(stage_dir), package)) else: changelog_target = ConcatPaths( (stage_dir, changelog_target)) if not os.path.isdir(changelog_target): os.makedirs(changelog_target) WriteFile(u'{}/changelog'.format(changelog_target), task_list[u'changelog'][1]) CMD_gzip = GetExecutable(u'gzip') if CMD_gzip: UpdateProgress(progress, GT(u'Compressing changelog')) c = u'{} -n --best "{}/changelog"'.format( CMD_gzip, changelog_target) clog_status = commands.getstatusoutput(c.encode(u'utf-8')) if clog_status[0]: ShowErrorDialog(GT(u'Could not compress changelog'), clog_status[1], warn=True, title=GT(u'Warning')) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Copyright *** # if create_copyright: UpdateProgress(progress, GT(u'Creating copyright')) WriteFile( u'{}/usr/share/doc/{}/copyright'.format( stage_dir, package), task_list[u'copyright']) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # Characters that should not be in filenames invalid_chars = (u' ', u'/') # *** Menu launcher *** # if u'launcher' in task_list: UpdateProgress(progress, GT(u'Creating menu launcher')) # This might be changed later to set a custom directory menu_dir = u'{}/usr/share/applications'.format(stage_dir) menu_filename = pg_menu.GetOutputFilename() # Remove invalid characters from filename for char in invalid_chars: menu_filename = menu_filename.replace(char, u'_') if not os.path.isdir(menu_dir): os.makedirs(menu_dir) WriteFile(u'{}/{}.desktop'.format(menu_dir, menu_filename), task_list[u'launcher']) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** md5sums file *** # # Good practice to create hashes before populating DEBIAN directory if u'md5sums' in task_list: UpdateProgress(progress, GT(u'Creating md5sums')) if not WriteMD5(stage_dir, parent=build_progress): # Couldn't call md5sum command build_progress.Cancel() progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Scripts *** # if u'scripts' in task_list: UpdateProgress(progress, GT(u'Creating scripts')) scripts = task_list[u'scripts'] for SCRIPT in scripts: script_name = SCRIPT script_text = scripts[SCRIPT] script_filename = ConcatPaths( (stage_dir, u'DEBIAN', script_name)) WriteFile(script_filename, script_text) # Make sure scipt path is wrapped in quotes to avoid whitespace errors os.chmod(script_filename, 0755) os.system((u'chmod +x "{}"'.format(script_filename))) # Individual scripts progress += 1 UpdateProgress(progress) # Entire script task progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Control file *** # UpdateProgress(progress, GT(u'Getting installed size')) # Get installed-size installed_size = os.popen( (u'du -hsk "{}"'.format(stage_dir))).readlines() installed_size = installed_size[0].split(u'\t') installed_size = installed_size[0] # Insert Installed-Size into control file control_data = pg_control.Get().split(u'\n') control_data.insert(2, u'Installed-Size: {}'.format(installed_size)) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # Create final control file UpdateProgress(progress, GT(u'Creating control file')) # dpkg fails if there is no newline at end of file control_data = u'\n'.join(control_data).strip(u'\n') # Ensure there is only one empty trailing newline # Two '\n' to show physical empty line, but not required # Perhaps because string is not null terminated??? control_data = u'{}\n\n'.format(control_data) WriteFile(u'{}/DEBIAN/control'.format(stage_dir), control_data, noStrip=u'\n') progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Final build *** # UpdateProgress(progress, GT(u'Running dpkg')) working_dir = os.path.split(stage_dir)[0] c_tree = os.path.split(stage_dir)[1] deb_package = u'{}.deb'.format(filename) # Move the working directory becuase dpkg seems to have problems with spaces in path os.chdir(working_dir) # HACK to fix file/dir permissions for ROOT, DIRS, FILES in os.walk(stage_dir): for D in DIRS: D = u'{}/{}'.format(ROOT, D) os.chmod(D, 0o0755) for F in FILES: F = u'{}/{}'.format(ROOT, F) if os.access(F, os.X_OK): os.chmod(F, 0o0755) else: os.chmod(F, 0o0644) # FIXME: Should check for working fakeroot & dpkg-deb executables build_status = commands.getstatusoutput( (u'{} {} -b "{}" "{}"'.format(GetExecutable(u'fakeroot'), GetExecutable(u'dpkg-deb'), c_tree, deb_package))) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** Delete staged directory *** # if u'rmstage' in task_list: UpdateProgress(progress, GT(u'Removing temp directory')) try: shutil.rmtree(stage_dir) except OSError: ShowErrorDialog(GT( u'An error occurred when trying to delete the build tree' ), parent=build_progress) progress += 1 if build_progress.WasCancelled(): build_progress.Destroy() return (dbrerrno.ECNCLD, None) # *** ERROR CHECK if u'lintian' in task_list: UpdateProgress(progress, GT(u'Checking package for errors')) # FIXME: Should be set as class memeber? CMD_lintian = GetExecutable(u'lintian') errors = commands.getoutput((u'{} {}'.format(CMD_lintian, deb))) if errors != wx.EmptyString: e1 = GT(u'Lintian found some issues with the package.') e2 = GT(u'Details saved to {}').format(filename) WriteFile(u'{}/{}.lintian'.format(build_path, filename), errors) DetailedMessageDialog(build_progress, GT(u'Lintian Errors'), ICON_INFORMATION, u'{}\n{}.lintian'.format(e1, e2), errors).ShowModal() progress += 1 # Close progress dialog wx.Yield() build_progress.Update(progress) build_progress.Destroy() # Build completed successfullly if not build_status[0]: return (dbrerrno.SUCCESS, deb_package) if PY_VER_MAJ <= 2: # Unicode decoder has trouble with certain characters. Replace any # non-decodable characters with � (0xFFFD). build_output = list(build_status[1]) # String & unicode string incompatibilities index = 0 for C in build_output: try: GS(C) except UnicodeDecodeError: build_output[index] = u'�' index += 1 build_status = (build_status[0], u''.join(build_output)) # Build failed return (build_status[0], build_status[1]) except: if build_progress: build_progress.Destroy() return (dbrerrno.EUNKNOWN, traceback.format_exc())
def LoadPaths(self, pathsList): if isinstance(pathsList, tuple): pathsList = list(pathsList) if not pathsList or not isinstance(pathsList, list): return False file_list = [] dir_list = {} prep = ProgressDialog(GetMainWindow(), GT(u'Processing Files'), GT(u'Scanning files ...'), style=wx.PD_APP_MODAL|wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT) # Only update the gauge every N files (hack until I figure out timer) update_interval = 450 count = 0 prep.Show() if not self.chk_preserve_top.GetValue(): for INDEX in reversed(range(len(pathsList))): path = pathsList[INDEX] if os.path.isdir(path): # Remove top-level directory from list pathsList.pop(INDEX) insert_index = INDEX for P in os.listdir(path): pathsList.insert(insert_index, ConcatPaths((path, P))) insert_index += 1 try: for P in pathsList: if prep.WasCancelled(): prep.Destroy() return False count += 1 if count >= update_interval: wx.Yield() prep.Pulse() count = 0 if not self.chk_individuals.GetValue() or os.path.isfile(P): file_list.append(P) continue if os.path.isdir(P): parent_dir = os.path.dirname(P) if parent_dir not in dir_list: dir_list[parent_dir] = [] for ROOT, DIRS, FILES in os.walk(P): if prep.WasCancelled(): prep.Destroy() return False wx.Yield() prep.SetMessage(GT(u'Scanning directory {} ...').format(ROOT)) count += 1 if count >= update_interval: wx.Yield() prep.Pulse() count = 0 for F in FILES: if prep.WasCancelled(): prep.Destroy() return False count += 1 if count >= update_interval: wx.Yield() prep.Pulse() count = 0 # os.path.dirname preserves top level directory ROOT = ROOT.replace(os.path.dirname(P), u'').strip(u'/') F = u'{}/{}'.format(ROOT, F).strip(u'/') if F not in dir_list[parent_dir]: dir_list[parent_dir].append(F) except: prep.Destroy() ShowErrorDialog(GT(u'Could not retrieve file list'), traceback.format_exc()) return False wx.Yield() prep.Pulse(GT(u'Counting Files')) file_count = len(file_list) count = 0 for D in dir_list: for F in dir_list[D]: file_count += 1 count += 1 if count >= update_interval: wx.Yield() prep.Pulse() count = 0 prep.Destroy() # Add files to directory list for F in file_list: f_name = os.path.basename(F) f_dir = os.path.dirname(F) if f_dir not in dir_list: dir_list[f_dir] = [] dir_list[f_dir].append(f_name) if file_count > warning_threshhold: count_warnmsg = GT(u'Importing {} files'.format(file_count)) count_warnmsg = u'{}. {}.'.format(count_warnmsg, GT(u'This could take a VERY long time')) count_warnmsg = u'{}\n{}'.format(count_warnmsg, GT(u'Are you sure you want to continue?')) if not ConfirmationDialog(GetMainWindow(), text=count_warnmsg).Confirmed(): return False return self.AddPaths(dir_list, file_count, showDialog=file_count >= efficiency_threshold)
compile_dirs = ( u'dbr', u'globals', u'wizbin', ) if not os.access(PATH_app, os.W_OK): print(u'ERROR: No write privileges for {}'.format(PATH_app)) sys.exit(errno.EACCES) print(u'Compiling Python modules (.py) to bytecode (.pyc) ...\n') print(u'Compiling root directory: {}'.format(PATH_app)) for F in os.listdir(PATH_app): if os.path.isfile(F) and F.endswith(u'.py') and F != u'init.py': F = ConcatPaths((PATH_app, F)) compileall.compile_file(F) print for D in os.listdir(PATH_app): D = ConcatPaths((PATH_app, D)) if os.path.isdir(D) and os.path.basename(D) in compile_dirs: print(u'Compiling directory: {}'.format(D)) compileall.compile_dir(D) print sys.exit(0) if u'clean' in parsed_commands:
value = L.replace(u'{}='.format(key), u'').replace(u'"', u'') break return value OS_name = GetOSInfo(u'DISTRIB_ID') OS_version = GetOSInfo(u'DISTRIB_RELEASE') OS_codename = GetOSInfo(u'DISTRIB_CODENAME') OS_upstream_name = GetOSInfo(u'DISTRIB_ID', True) OS_upstream_version = GetOSInfo(u'DISTRIB_RELEASE', True) OS_upstream_codename = GetOSInfo(u'DISTRIB_CODENAME', True) ## File where distribution code names cache is stored FILE_distnames = ConcatPaths((PATH_cache, u'distnames')) ## Retrieves distribution names from remote Debian site # # NOTE: If site layout changes, function will need updated # \param obsolete # Include obsolete distributions # \param unstable # Include testing & unstable distributions # \param generic # Include generic names 'oldstable', 'stable', 'testing', & 'unstable' def _get_debian_distnames(unstable=True, obsolete=False, generic=False): ref_site = u'https://wiki.debian.org/DebianReleases' # Names added statically are continually used by Debian project
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() file_list = GetField(pgid.FILES, inputid.LIST) exe_list = file_list.GetExecutables(False) for EXE in exe_list: INDEX = file_list.GetIndex(EXE) # Get the filename from the source file_name = file_list.GetFilename(INDEX) #file_name = EXE.GetBasename() # Where the file linked to will be installed # FIXME: FileItem.GetTarget() is not accurate file_target = file_list.GetTarget(EXE) self.Executables.Add( FileItem(file_name, ConcatPaths(file_target, file_name), ignore_timestamp=True)) # retrieve nested executables # FIXME: symlinks may cause problems here for FITEM in file_list.GetFileItems(): if FITEM.IsDirectory(): # recurse into subdirectories toplevel = FITEM.GetPath() for ROOT, DIRS, FILES in os.walk(toplevel): for FILE in FILES: fullpath = ConcatPaths(ROOT, FILE) DIR = os.path.dirname( fullpath[len(toplevel):]).strip(u'/') relpath = ConcatPaths(FITEM.GetBasename(), DIR, FILE).strip(u'/') if os.path.isfile(fullpath) and os.access( fullpath, os.X_OK): fulltarget = ConcatPaths( FITEM.GetTarget(), relpath) # check if item is already added to list duplicate = False for EXE in exe_list: existingtarget = ConcatPaths( EXE.GetTarget(), file_list.GetFilename(EXE)) if fulltarget == existingtarget: duplicate = True break if duplicate: Logger.Warn( __name__, u'Not adding executable with duplicate target: {}' .format(fulltarget)) continue Logger.Debug( __name__, u'Adding nested executable: {}'.format( relpath)) self.Executables.Add( FileItem(relpath, ConcatPaths( FITEM.GetTarget(), relpath), ignore_timestamp=True)) elif event_id in (btnid.REMOVE, wx.WXK_DELETE): self.Executables.RemoveSelected()
# -*- coding: utf-8 -*- ## \package globals.bitmaps # MIT licensing # See: docs/LICENSE.txt from dbr.image import GetBitmap from globals.paths import ConcatPaths from globals.paths import PATH_bitmaps LOGO = ConcatPaths((PATH_bitmaps, u'icon/64/logo.png')) ICON_ERROR = GetBitmap(u'error', 64, u'icon') ICON_EXCLAMATION = ICON_ERROR ICON_QUESTION = GetBitmap(u'question', 64, u'icon') ICON_INFORMATION = GetBitmap(u'info', 64, u'icon') ICON_WARNING = GetBitmap(u'warn', 64, u'icon') ICON_CLOCK = GetBitmap(u'clock', 16, u'icon') ICON_GLOBE = GetBitmap(u'globe', 16, u'icon') ICON_LOGO = GetBitmap(u'logo', 16, u'icon')