Example #1
0
    def OnToggle(self, event=None):
        enabled = GetField(self, chkid.ENABLE).IsChecked()

        # Fields that should not be disabled
        skip_ids = (
            chkid.ENABLE,
            btnid.BROWSE,
            txtid.FNAME,
        )

        for LIST in inputid, chkid, listid, btnid:
            for ID in LIST.IdList:
                if ID not in skip_ids:
                    field = GetField(self, ID)

                    if isinstance(field, wx.Window):
                        field.Enable(enabled)

        # Disable/Enable static text labels
        st_labels = GetAllTypeFields(self, wx.StaticText)
        for ST in st_labels:
            if ST.Id not in skip_ids:
                ST.Enable(enabled)

        self.OnSetCustomFilename()
Example #2
0
 def Reset(self):
     field_ids = (
         chkid,
         inputid,
         listid,
         selid,
         )
     
     for IDTYPE in field_ids:
         idlist = IDTYPE.IdList
         
         for ID in idlist:
             if ID not in self.IgnoreResetIds:
                 field = GetField(self, ID)
                 
                 if isinstance(field, wx.Window):
                     field.Reset()
     
     # Pages that use MultiTemplate instances
     multit_ids = (
         pgid.MAN,
         pgid.LAUNCHERS,
         )
     
     if self.Id in multit_ids:
         NBLIST = GetAllTypeFields(self, Notebook)
         
         if NBLIST:
             for NB in NBLIST:
                 MT = NB.GetContainingSizer()
                 
                 if isinstance(MT, MultiTemplate):
                     MT.Reset()
Example #3
0
    def SetCategory(self, event=None):
        try:
            ID = event.GetKeyCode()

        except AttributeError:
            ID = event.GetEventObject().GetId()

        cat = self.ti_category.GetValue()
        cat = cat.split()
        cat = u''.join(cat)

        lst_categories = GetField(self, listid.CAT)

        if ID in (wx.ID_ADD, wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            lst_categories.InsertStringItem(lst_categories.GetItemCount(), cat)

        elif ID in (wx.ID_REMOVE, wx.WXK_DELETE):
            if lst_categories.GetItemCount(
            ) and lst_categories.GetSelectedItemCount():
                cur_cat = lst_categories.GetFirstSelected()
                lst_categories.DeleteItem(cur_cat)

        elif ID == wx.ID_CLEAR:
            if lst_categories.GetItemCount():
                if ConfirmationDialog(
                        GetMainWindow(), GT(u'Confirm'),
                        GT(u'Clear categories?')).ShowModal() in (wx.ID_OK,
                                                                  wx.OK):
                    lst_categories.DeleteAllItems()

        if event:
            event.Skip()
Example #4
0
    def ScrollToEnd(self):
        pnl_bg = GetField(self, pnlid.BACKGROUND)

        pnl_bg.SetScrollPos(wx.VERTICAL, pnl_bg.GetScrollLines(wx.VERTICAL))

        pnl_bg.Refresh()
        self.Refresh()
Example #5
0
        def set_value(option):
            key = option.GetName()
            value = None

            if key in menu_definitions:
                value = menu_definitions[key]

                if not TextIsEmpty(value):
                    if option in self.opts_input:
                        option.SetValue(value)
                        return True

                    elif option in self.opts_choice:
                        if option.SetStringSelection(value):
                            return True

                    elif option in self.opts_list:
                        lst_categories = GetField(self, listid.CAT)

                        if key == lst_categories.GetName():
                            value = value.split(u';')

                            if value:
                                for X, val in enumerate(value):
                                    lst_categories.InsertStringItem(X, val)
                                return True

            return False
Example #6
0
	def ToggleButtons(self):
		parent = self.GetParent()

		for ID in self.TabButtonIds:
			button = GetField(parent, ID)

			if button:
				button.Enable(self.HasTabs())
Example #7
0
    def OnClearCategories(self, event=None):
        cats = GetField(self, listid.CAT)

        if cats.GetItemCount():
            clear = ConfirmationDialog(GetMainWindow(), GT(u'Confirm'),
                                       GT(u'Clear categories?'))

            if clear.Confirmed():
                cats.DeleteAllItems()
Example #8
0
    def GetAllItems(self):
        pnl_bg = GetField(self, pnlid.BACKGROUND)
        items = []

        for item in pnl_bg.GetChildren():
            if isinstance(item, wx.CheckBox):
                items.append(item)

        return tuple(items)
Example #9
0
    def OnClearCategories(self, event=None):
        cats = GetField(self, listid.CAT)

        if cats.HasSelected():
            clear = ConfirmationDialog(GetMainWindow(), GT(u'Confirm'),
                                       GT(u'Clear categories?'))

            if clear.Confirmed():
                cats.Clear()
Example #10
0
    def GetOutputFilename(self):
        if not GetField(self, chkid.FNAME).GetValue():
            filename = GetField(self,
                                inputid.FNAME).GetValue().strip(u' ').replace(
                                    u' ', u'_')
            if not TextIsEmpty(filename):
                return filename

        return GetField(self, inputid.NAME).GetValue().strip(u' ').replace(
            u' ', u'_')
Example #11
0
 def OnSelectLicense(self, event=None):
     choice = GetField(self, selid.LICENSE)
     if choice:
         template = choice.GetString(choice.GetSelection())
         
         if template in self.custom_licenses:
             self.btn_template_simple.Disable()
         
         else:
             self.btn_template_simple.Enable()
         
         self.SetLicenseTooltip()
Example #12
0
    def GetSaveData(self):
        if GetField(self, chkid.ENABLE).GetValue():
            data = self.GetLauncherInfo()
            data = u'\n'.join(data.split(u'\n')[1:])

            if not GetField(self, chkid.FNAME).GetValue():
                data = u'[FILENAME={}]\n{}'.format(
                    GetField(self, inputid.FNAME).GetValue(), data)

            return u'<<MENU>>\n1\n{}\n<</MENU>>'.format(data)

        else:
            return u'<<MENU>>\n0\n<</MENU>>'
Example #13
0
    def OnClearCache(self, event=None):
        if os.path.isfile(FILE_distnames):
            os.remove(FILE_distnames)

            # Update list on changelog page
            distname_input = GetField(pgid.CHANGELOG, inputid.DIST)
            if isinstance(distname_input, OwnerDrawnComboBox):
                distname_input.Set(GetOSDistNames())

            self.btn_preview.Disable()

        cache_exists = os.path.exists(FILE_distnames)

        self.btn_preview.Enable(cache_exists)
        return not cache_exists
Example #14
0
	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()
Example #15
0
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)))
Example #16
0
    def Reset(self):
        field_ids = (
            chkid,
            inputid,
            listid,
            selid,
        )

        for IDTYPE in field_ids:
            idlist = IDTYPE.IdList

            for ID in idlist:
                if ID not in self.IgnoreResetIds:
                    field = GetField(self, ID)

                    if isinstance(field, wx.Window):
                        field.Reset()
Example #17
0
    def OnCatSelect(self, event=None):
        btn_cat_clr = GetField(self, wx.ID_CLEAR)
        lst_cat = GetField(self, listid.CAT)

        if btn_cat_clr and lst_cat:
            if FieldEnabled(btn_cat_clr):
                if not lst_cat.HasSelected():
                    btn_cat_clr.Disable()

            else:
                if lst_cat.HasSelected():
                    btn_cat_clr.Enable()
Example #18
0
    def AddItem(self, label, checked=False):
        # Yield for progress dialog pulse updates
        wx.Yield()

        # FIXME: Static lines are counted
        item_index = self.GetItemCount()

        #Logger.Debug(__name__, GT(u'Lintian tag: {}; Set checked: {}').format(label, checked))

        pnl_bg = GetField(self, pnlid.BACKGROUND)
        lyt_bg = pnl_bg.GetSizer()

        lyt_bg.Add(wx.CheckBox(pnl_bg, label=label), 1, wx.EXPAND)
        lyt_bg.Add(wx.StaticLine(pnl_bg, style=wx.LI_HORIZONTAL), 0, wx.EXPAND)

        if checked:
            check_box = self.GetItem(item_index)

            if isinstance(check_box, wx.CheckBox):
                check_box.SetValue(True)

        pnl_bg.Layout()
        self.Layout()
Example #19
0
 def OnRefreshList(self, event=None):
     # FIXME: Ignore symbolic links???
     self.custom_licenses = GetLocalLicenses()
     
     licenses = list(self.custom_licenses)
     
     # System licenses are not added to "custom" list
     for LIC in GetSysLicenses():
         if LIC not in licenses:
             licenses.append(LIC)
     
     for LIC in GetCustomLicenses():
         if LIC not in licenses:
             licenses.append(LIC)
             self.custom_licenses.append(LIC)
     
     self.custom_licenses.sort(key=GS.lower)
     
     sel_templates = GetField(self, selid.LICENSE)
     
     selected = None
     if sel_templates.GetCount():
         selected = sel_templates.GetStringSelection()
     
     sel_templates.Set(sorted(licenses, key=GS.lower))
     
     if selected:
         if not sel_templates.SetStringSelection(selected):
             # Selected template file was not found
             sel_templates.SetSelection(sel_templates.GetDefaultValue())
             
             # Update short template button enabled state
             self.OnSelectLicense()
     
     else:
         sel_templates.SetSelection(sel_templates.GetDefaultValue())
Example #20
0
    def OnOtherRemove(self, event=None):
        pnl_other = GetField(self, inputid.OTHER)

        # FIXME: Show confirmation dialog

        if pnl_other:
            if pnl_other.HasSelected():
                remove = ConfirmationDialog(
                    GetMainWindow(), GT(u'Custom Fields'),
                    GT(u'Remove all selected custom fields?'))

                if remove.Confirmed():
                    pnl_other.RemoveSelected()

            btn_remove = GetField(self, wx.ID_REMOVE)

            if btn_remove and FieldEnabled(btn_remove):
                btn_remove.Enable(pnl_other.HasSelected())
Example #21
0
    def Reset(self):
        chk_filename = GetField(self, chkid.FNAME)

        chk_filename.SetValue(chk_filename.Default)
        GetField(self, inputid.FNAME).Clear()

        for IDS in inputid, chkid, listid:
            idlist = IDS.IdList

            for ID in idlist:
                field = GetField(self, ID)

                if isinstance(field, wx.Window):
                    field.Reset()

        self.OnToggle()
Example #22
0
    def IsSelected(self, section):
        if isinstance(section, int):
            section = self.GetSection(section)

        return GetField(section, inputid.CHECK).GetValue()
Example #23
0
    def OnBuild(self, event=None):
        if event:
            event.Skip()

        # Show control file preview for editing
        if UsingTest(u'alpha') and self.chk_editctrl.GetValue():
            self.EditControl()

        wizard = GetWizard()

        pg_control = wizard.GetPage(pgid.CONTROL)
        pg_files = wizard.GetPage(pgid.FILES)
        pg_launcher = wizard.GetPage(pgid.LAUNCHERS)

        required_fields = {
            GT(u'Control'): pg_control.GetRequiredFields(),
        }

        # Check if launchers are enabled for build
        if pg_launcher.GetLaunchersCount():
            required_fields[GT(
                u'Menu Launcher')] = pg_launcher.GetRequiredFields()

            # FIXME: Old code won't work with multiple launchers
            for RF in required_fields[GT(u'Menu Launcher')]:
                Logger.Debug(
                    __name__,
                    GT(u'Required field (Menu Launcher): {}').format(
                        RF.GetName()))

        for p_name in required_fields:
            Logger.Debug(__name__, GT(u'Page name: {}').format(p_name))
            for F in required_fields[p_name]:
                if not isinstance(F, wx.StaticText) and TextIsEmpty(
                        F.GetValue()):
                    f_name = F.GetName()

                    msg_l1 = GT(u'One of the required fields is empty:')
                    msg_full = u'{}: {} ➜ {}'.format(msg_l1, p_name, f_name)

                    Logger.Warn(__name__, msg_full)

                    DetailedMessageDialog(GetMainWindow(),
                                          GT(u'Cannot Continue'),
                                          ICON_EXCLAMATION,
                                          text=msg_full).ShowModal()

                    for P in wizard.GetAllPages():
                        if P.GetTitle() == p_name:
                            Logger.Debug(
                                __name__,
                                GT(u'Showing page with required field: {}').
                                format(p_name))
                            wizard.ShowPage(P.GetId())

                    return

        if GetField(pg_files, inputid.LIST).MissingFiles():
            ShowErrorDialog(GT(u'Files are missing in file list'),
                            warn=True,
                            title=GT(u'Warning'))

            wizard.ShowPage(pgid.FILES)

            return

        ttype = GT(u'Debian Packages')
        save_dialog = GetFileSaveDialog(GetMainWindow(), GT(u'Build Package'),
                                        u'{} (*.deb)|*.deb'.format(ttype),
                                        u'deb')

        package = GetFieldValue(pg_control, inputid.PACKAGE)
        version = GetFieldValue(pg_control, inputid.VERSION)
        arch = GetFieldValue(pg_control, inputid.ARCH)
        save_dialog.SetFilename(u'{}_{}_{}.deb'.format(package, version, arch))

        if ShowDialog(save_dialog):
            self.Build(save_dialog.GetPath())
Example #24
0
    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()
Example #25
0
 def GetSelectedName(self):
     return GetField(self, selid.LICENSE).GetStringSelection()
Example #26
0
    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())
Example #27
0
 def GetPackageName(self):
     return GetField(self, inputid.PACKAGE).GetValue()
Example #28
0
    def GetCtrlInfo(self):
        pg_depends = GetPage(pgid.DEPENDS)

        ctrl_list = []
        synopsis = None
        description = None
        # Email will be set if maintainer changed to True
        maintainer = False

        # Text input fields
        for field in self.grp_input:
            field_name = field.GetName().title()
            field_value = field.GetValue()

            if FieldEnabled(field) and not TextIsEmpty(field_value):
                Logger.Debug(__name__,
                             GT(u'Exporting {} field').format(field_name))

                # Strip leading & trailing spaces, tabs, & newlines
                field_value = field_value.strip(u' \t\n')

                if field_name == u'Synopsis':
                    synopsis = u'{}: {}'.format(u'Description', field_value)
                    continue

                if field_name == u'Description':
                    description = field_value.split(u'\n')
                    for line_index in range(len(description)):
                        # Remove trailing whitespace
                        description[line_index] = description[
                            line_index].rstrip()

                        if TextIsEmpty(description[line_index]):
                            # Empty lines are formatted with one space indentation & a period
                            description[line_index] = u' .'

                        else:
                            # All other lines are formatted with one space indentation
                            description[line_index] = u' {}'.format(
                                description[line_index])

                    description = u'\n'.join(description)
                    continue

                if field_name in (u'Package', u'Version'):
                    # Don't allow whitespace in package name & version
                    ctrl_list.append(u'{}: {}'.format(
                        field_name, u'-'.join(field_value.split(u' '))))
                    continue

                if field_name == u'Email':
                    if maintainer and ctrl_list:
                        # Append email to end of maintainer string
                        for ctrl_index in range(len(ctrl_list)):
                            if ctrl_list[ctrl_index].startswith(
                                    u'Maintainer: '):
                                Logger.Debug(__name__, u'Found maintainer')
                                ctrl_list[ctrl_index] = u'{} <{}>'.format(
                                    ctrl_list[ctrl_index], field_value)
                                break

                    continue

                # Don't use 'continue' on this statement
                if field_name == u'Maintainer':
                    maintainer = True

                # The rest of the fields
                ctrl_list.append(u'{}: {}'.format(field_name, field_value))

        # Selection box fields
        for field in self.grp_select:
            field_name = field.GetName().title()
            field_value = field.GetStringSelection()

            if FieldEnabled(field) and not TextIsEmpty(field_value):
                Logger.Debug(__name__,
                             GT(u'Exporting {} field').format(field_name))

                # Strip leading & trailing spaces, tabs, & newlines
                field_value = field_value.strip(u' \t\n')

                ctrl_list.append(u'{}: {}'.format(field_name, field_value))

        if self.chk_essential.GetValue():
            ctrl_list.append(u'Essential: yes')

        # Dependencies & conflicts
        dep_list = []  # Depends
        pre_list = []  # Pre-Depends
        rec_list = []  # Recommends
        sug_list = []  # Suggests
        enh_list = []  # Enhances
        con_list = []  # Conflicts
        rep_list = []  # Replaces
        brk_list = []  # Breaks

        all_deps = {
            u'Depends': dep_list,
            u'Pre-Depends': pre_list,
            u'Recommends': rec_list,
            u'Suggests': sug_list,
            u'Enhances': enh_list,
            u'Conflicts': con_list,
            u'Replaces': rep_list,
            u'Breaks': brk_list,
        }

        # Get amount of items to add
        dep_area = GetField(pg_depends, inputid.LIST)
        dep_count = dep_area.GetItemCount()
        count = 0
        while count < dep_count:
            # Get each item from dependencies page
            dep_type = dep_area.GetItem(count, 0).GetText()
            dep_val = dep_area.GetItem(count, 1).GetText()
            for item in all_deps:
                if dep_type == item:
                    all_deps[item].append(dep_val)

            count += 1

        for item in all_deps:
            if len(all_deps[item]) != 0:
                ctrl_list.append(u'{}: {}'.format(item,
                                                  u', '.join(all_deps[item])))

        if synopsis:
            ctrl_list.append(synopsis)

            # Long description is only added if synopsis is not empty
            if description:
                ctrl_list.append(description)

        # dpkg requires empty newline at end of file
        return u'\n'.join(ctrl_list).strip(u'\n') + u'\n'
Example #29
0
    def OnUpdateCache(self, event=None):
        try:
            # Timer must be started before executing new thread
            self.timer.Start(100)

            if not self.timer.IsRunning():
                self.error_message = GT(
                    u'Could not start progress dialog timer')
                self.CheckErrors()
                return False

            self.Disable()

            # Start new thread for updating cache in background
            Thread(self.UpdateCache, None).Start()

            # Create the progress dialog & start timer
            # NOTE: Progress dialog is reset by timer stop event
            self.progress = ProgressDialog(
                self,
                message=GT(u'Contacting remote sites'),
                style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)

            # Use ShowModal to wait for timer to stop before continuing
            self.progress.ShowModal()

            self.Enable()

            if self.CheckErrors():
                return False

            # FIXME: Should check timestamps to make sure file was updated
            cache_updated = os.path.isfile(FILE_distnames)

            if cache_updated:
                distname_input = GetField(pgid.CHANGELOG, inputid.DIST)

                if isinstance(distname_input, OwnerDrawnComboBox):
                    distname_input.Set(GetOSDistNames())

                else:
                    ShowMessageDialog(GT(
                        u'The distribution names cache has been updated but Debreate needs to restart to reflect the changes on the changelog page'
                    ),
                                      parent=self,
                                      linewrap=410)

            self.btn_preview.Enable(cache_updated)

            return cache_updated

        except:
            # Make sure dialog is re-enabled
            self.Enable()

            # Make sure progress dialog & background thread instances are reset to None
            if self.progress:
                self.progress.EndModal(0)
                self.progress = None

            cache_exists = os.path.isfile(FILE_distnames)

            err_msg = GT(
                u'An error occurred when trying to update the distribution names cache'
            )
            err_msg2 = GT(
                u'The cache file exists but may not have been updated')
            if cache_exists:
                err_msg = u'{}\n\n{}'.format(err_msg, err_msg2)

            ShowErrorDialog(err_msg, traceback.format_exc(), self)

            self.btn_preview.Enable(cache_exists)

        return False
Example #30
0
    def BuildPrep(self):
        # Declare these here in case of error before dialogs created
        save_dia = None
        prebuild_progress = None

        try:
            # List of tasks for build process
            # 'stage' should be very first task
            task_list = {}

            # Control page
            pg_control = GetPage(pgid.CONTROL)
            fld_package = GetField(pg_control, inputid.PACKAGE)
            fld_version = GetField(pg_control, inputid.VERSION)
            fld_maint = GetField(pg_control, inputid.MAINTAINER)
            fld_email = GetField(pg_control, inputid.EMAIL)
            fields_control = (
                fld_package,
                fld_version,
                fld_maint,
                fld_email,
            )

            # Menu launcher page
            pg_launcher = GetPage(pgid.MENU)

            # Check to make sure that all required fields have values
            required = list(fields_control)

            if pg_launcher.IsOkay():
                task_list[u'launcher'] = pg_launcher.Get()

                required.append(GetField(pg_launcher, inputid.NAME))

                if not GetField(pg_launcher, chkid.FNAME).GetValue():
                    required.append(GetField(pg_launcher, inputid.FNAME))

            for item in required:
                if TextIsEmpty(item.GetValue()):
                    field_name = GT(item.GetName().title())
                    page_name = pg_control.GetName()
                    if item not in fields_control:
                        page_name = pg_launcher.GetName()

                    return (dbrerrno.FEMPTY,
                            u'{} ➜ {}'.format(page_name, field_name))

            # Get information from control page for default filename
            package = fld_package.GetValue()
            # Remove whitespace
            package = package.strip(u' \t')
            package = u'-'.join(package.split(u' '))

            version = fld_version.GetValue()
            # Remove whitespace
            version = version.strip(u' \t')
            version = u''.join(version.split())

            arch = GetField(pg_control, inputid.ARCH).GetStringSelection()

            # Dialog for save destination
            ttype = GT(u'Debian packages')
            save_dia = wx.FileDialog(
                self, GT(u'Save'), os.getcwd(), wx.EmptyString,
                u'{}|*.deb'.format(ttype),
                wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT | wx.FD_CHANGE_DIR)
            save_dia.SetFilename(u'{}_{}_{}.deb'.format(
                package, version, arch))
            if not save_dia.ShowModal() == wx.ID_OK:
                return (dbrerrno.ECNCLD, None)

            build_path = os.path.split(save_dia.GetPath())[0]
            filename = os.path.split(save_dia.GetPath())[1].split(u'.deb')[0]

            # Control, menu, & build pages not added to this list
            page_checks = (
                (pgid.FILES, u'files'),
                (pgid.SCRIPTS, u'scripts'),
                (pgid.CHANGELOG, u'changelog'),
                (pgid.COPYRIGHT, u'copyright'),
            )

            # Install step is not added to this list
            # 'control' should be after 'md5sums'
            # 'build' should be after 'control'
            other_checks = (
                (self.chk_md5, u'md5sums'),
                (self.chk_strip, u'strip'),
                (self.chk_rmstage, u'rmstage'),
                (self.chk_lint, u'lintian'),
            )

            prep_task_count = len(page_checks) + len(other_checks)

            progress = 0

            wx.Yield()
            prebuild_progress = ProgressDialog(GetMainWindow(),
                                               GT(u'Preparing to build'),
                                               maximum=prep_task_count)

            if wx.MAJOR_VERSION < 3:
                # Resize dialog for better fit
                pb_size = prebuild_progress.GetSizeTuple()
                pb_size = (pb_size[0] + 200, pb_size[1])
                prebuild_progress.SetSize(pb_size)
                prebuild_progress.CenterOnParent()

            for PID, id_string in page_checks:
                wx.Yield()
                prebuild_progress.Update(progress,
                                         GT(u'Checking {}').format(id_string))

                wizard_page = GetPage(PID)
                if wizard_page.IsOkay():
                    task_list[id_string] = wizard_page.Get()

                progress += 1

            for task_check, id_string in other_checks:
                wx.Yield()
                prebuild_progress.Update(
                    progress,
                    GT(u'Testing for: {}').format(task_check.GetLabel()))

                if task_check.GetValue():
                    task_list[id_string] = None

                progress += 1

            # Close progress dialog
            wx.Yield()
            prebuild_progress.Update(progress)
            prebuild_progress.Destroy()

            return (dbrerrno.SUCCESS, (task_list, build_path, filename))

        except:
            if save_dia:
                save_dia.Destroy()

            if prebuild_progress:
                prebuild_progress.Destroy()

            return (dbrerrno.EUNKNOWN, traceback.format_exc())