Ignore:
Timestamp:
Jun 16, 2017, 1:39:45 PM (3 years ago)
Author:
Juanma
Message:

appimage fully functional

Location:
lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/appImageManager.py

    r5188 r5199  
    1212class appimagemanager:
    1313        def __init__(self):
    14                 self.example='This is an example plugin'
    15                 self.dbg=0
     14                self.dbg=1
    1615                self.progress=0
    1716                #This dict defines wich package_type relies on what action
     
    2221                self.result['data']={}
    2322                self.result['status']={}
    24                 self.appImageFolder='/tmp'
    25                 self.pkginfo=self.appImageFolder+'/.bundles.json'
     23                self.appImageFolder='/opt/bundles/appimg'
     24                self.repoPage='https://dl.bintray.com/probono/AppImages'
     25                #To get the description of an app we must go to a specific url.
     26                #$(appname) we'll be replaced with the appname so the url matches the right one.
     27                #If other site has other url naming convention it'll be mandatory to define it with the appropiate replacements
     28                self.infoPage='https://bintray.com/probono/AppImages/$(appname)'
    2629                self.count=0
    2730        #def __init__
     
    4144
    4245        def execute_action(self,action,applist=None):
     46                self._chk_installDir()
    4347                self.progress=0
    4448                self.result['status']={'status':-1,'msg':''}
    4549                self.result['data']=''
    4650                dataList=[]
    47                 if action=='loadCatalogue':
    48                         dataList.append(self._download_appImg_catalogue())
    49                 else:
    50                         for appInfo in applist:
    51                                 if action=='install':
    52                                         dataList.append(self._install_appImg(appInfo))
    53                                 if action=='remove':
    54                                         dataList.append(self._remove_appImg(appInfo))
    55                                 if action=='pkginfo':
    56                                         dataList.append(self._get_info(appInfo))
     51                for appInfo in applist:
     52                        if action=='install':
     53                                dataList.append(self._install_appImg(appInfo))
     54                        if action=='remove':
     55                                dataList.append(self._remove_appImg(appInfo))
     56                        if action=='pkginfo':
     57                                dataList.append(self._get_info(appInfo))
    5758                self.result['data']=list(dataList)
    5859                self.progress=100
     
    7677                        self.progress=limit
    7778
     79        def _chk_installDir(self):
     80                msg_status=True
     81                if not os.path.isdir(self.appImageFolder):
     82                        try:
     83                                os.makedirs(self.appImageFolder)
     84                        except:
     85                                msg_status=False
     86                return msg_status                               
     87
    7888        def _install_appImg(self,appInfo):
    7989                appInfo=self._get_info(appInfo)
     
    8191                        self._set_status(4)
    8292                else:
    83                         appImgUrl='https://dl.bintray.com/probono/AppImages/'+appInfo['appImage']
     93                        appImgUrl=self.repoPage+'/'+appInfo['appImage']
    8494                        self._debug("Downloading "+appImgUrl)
    85                         dest_path='/tmp/'+appInfo['appImage']
     95                        dest_path=self.appImageFolder+'/'+appInfo['appImage']
    8696                        if appImgUrl:
    8797                                try:
     
    99109                                        os.chmod(dest_path, st.st_mode | 0o111)
    100110                                        self._set_status(0)
    101                                         self._write_info(appInfo,'install')
    102111                                except:
    103112                                        self._set_status(5)
     
    108117
    109118        def _remove_appImg(self,appInfo):
    110                 appInfo=self._get_info(appInfo)
    111                 if appInfo['state']=='available':
    112                         self._set_status(3)
    113                 else:
     119                self._debug("Removing "+appInfo['appImage'])
     120                if os.path.isfile(self.appImageFolder+'/'+appInfo['appImage']):
    114121                        try:
    115122                                call([self.appImageFolder+"/"+appInfo['appImage'], "--remove-appimage-desktop-integration"])
    116123                                os.remove(self.appImageFolder+"/"+appInfo['appImage'])
    117                                 self._write_info(appInfo,'remove')
    118124                                self._set_status(0)
    119125                        except:
     
    121127                return(appInfo)
    122128        #def _remove_appImg
    123        
    124         def _write_info(self,appInfo,action):
    125                 infoBundle={}
    126                 if os.path.isfile(self.pkginfo):
    127                         try:
    128                                 infoFile=open(self.pkginfo).read()
    129                                 infoBundle=json.loads(infoFile)
    130                         except:
    131                                 pass
    132                 if action=='remove':
    133                         infoBundle.pop(appInfo['appImage'],None)
    134                 if action=='install':
    135                         infoBundle.update({appInfo['appImage']:'installed'})
    136                 try:
    137                         with open(self.pkginfo, 'w') as infoFile:
    138                             infoBundle=json.dump(infoBundle,infoFile)
    139                 except:
    140                         pass
    141         #def _write_info
    142129
    143130        def _get_info(self,appInfo):
    144131                appInfo['state']='available'
    145                 if os.path.isfile(self.pkginfo):
    146                         try:
    147                                 infoFile=open(self.pkginfo).read()
    148                                 infoBundle=json.loads(infoFile)
    149                                 if appInfo['appImage'] in infoBundle:
    150                                         appInfo['state']=infoBundle[appInfo['appImage']]
    151                         except:
    152                                 pass
     132                if os.path.isfile(self.appImageFolder+'/'+appInfo['appImage']):
     133                        appInfo['state']='installed'
    153134                self._set_status(0)
    154135                return(appInfo)
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/infoManager.py

    r5133 r5199  
    153153                                        appInfo['video']=appInfo['video'].replace('watch?v=','embed/')
    154154                        for bundle in app.get_bundles():
    155                                 print(bundle)
    156155                                if bundle.get_kind()==0:
    157                                         print(bundle.get_kind())
    158156                                #F***g appstream returns unknown for all the possible types
    159157                                        if bundle.get_id().endswith('AppImage'):
    160158                                                appInfo['appImage']=bundle.get_id()
    161                                                 appInfo['description']='This is an appImage bundle. It comes from 3rd party providers and hasn\'t be tested by our devs. Please use it carefully\n'+app.get_description(localeItem)
    162159                                        else:
    163160                                                appInfo['installerUrl']=bundle.get_id()
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/loadStore.py

    r5188 r5199  
    1111import threading
    1212import time
     13import datetime
     14import gettext
     15gettext.textdomain('python3-lliurex-store')
     16_=gettext.gettext
    1317
    1418class loadstore:
     
    1923                self.progress=0
    2024                self.error=0
     25                self.bundleDir="/var/lib/lliurexstore/bundles"
     26                self.bundleTypes=['appimg']
     27                self.zmdCatalogueDir='/var/lib/lliurexstore/zmds'
    2128        #def __init__
    2229
     
    4350                if action=='load':
    4451                        self._load_store(self.store,loadBundles)
    45                 self.progress=100
     52#               self.progress=100
    4653                return (self.store)
    4754        #def execute_action
     
    6168                                print ("Failed to load"+str(flag))
    6269                                pass
     70                store=self.load_zmds_catalog(store)
    6371                store=self._sanitize_store(store)
    6472                if loadBundles:
    65                         self._download_appImg_catalogue()
    66                         store=self.load_appImg_catalog(store)
     73                        if self._download_bundles_catalogue():
     74                                store=self.load_bundles_catalog(store)
    6775                self.store=store
    6876                return(store)
    6977        #def load_store
    7078
    71         def load_appImg_catalog(self,store):
     79        def load_bundles_catalog(self,store):
     80                if os.path.exists(self.bundleDir):
     81                        for bundleType in self.bundleTypes:
     82                                store=self._generic_file_load(self.bundleDir+'/'+bundleType,store)
     83                return(store)
     84        #def load_bundles_catalog(self)
     85
     86        def load_zmds_catalog(self,store):
     87                if os.path.exists(self.zmdCatalogueDir):
     88                        store=self._generic_file_load(self.zmdCatalogueDir,store)
     89                return(store)
     90        #def load_zmds_catalog(self)
     91
     92        def _generic_file_load(self,filesDir,store):
    7293                iconPath='/usr/share/icons/hicolor/128x128'
    73 #               lliurex_dir="/home/juanma/svn/xenial/devtools/appImgdep11/dep11"
    74                 lliurex_dir="/tmp"
    75                 if os.path.exists(lliurex_dir):
    76                         for lliurex in os.listdir(lliurex_dir):
    77                                 if lliurex.endswith('appdata.xml'):
    78                                         storePath=Gio.File.new_for_path(lliurex_dir+'/'+lliurex)
    79                                         self._debug("Adding file "+lliurex_dir+'/'+lliurex)
    80                                         try:
    81                                                 store.from_file(storePath,iconPath,None)
    82                                         except Exception as e:
    83                                                 self._debug("Couldn't add file "+lliurex+" to store")
    84                                                 self._debug("Reason: "+str(e))
    85                 return(store)
    86 
    87         #def load_appImg_catalog(self)
    88 
     94                for appFile in os.listdir(filesDir):
     95                        if appFile.endswith('appdata.xml'):
     96                                storePath=Gio.File.new_for_path(filesDir+'/'+appFile)
     97                                self._debug("Adding file "+filesDir+'/'+appFile)
     98                                try:
     99                                        store.from_file(storePath,iconPath,None)
     100                                except Exception as e:
     101                                        self._debug("Couldn't add file "+appFile+" to store")
     102                                        self._debug("Reason: "+str(e))
     103                return(store)
     104       
    89105        def _parse_desktop(self,store): #DEPRECATED. Loads the apps from the available desktop files
    90106                desktopDir='/usr/share/applications'
     
    232248        #def _apply_blacklist
    233249
    234         def _download_appImg_catalogue(self):
     250        def _download_bundles_catalogue(self):
    235251                CURSOR_UP='\033[F'
    236252                ERASE_LINE='\033[K'
    237                 outfile='appimage.yml'
    238                 outdir="/usr/share/metainfo"
    239                 outdir="/tmp"
    240253                content=''
    241254                applist=[]
    242255                progressBar="#"
    243                 repolist=['https://dl.bintray.com/probono/AppImages']
     256                repoList={'appimg':['https://dl.bintray.com/probono/AppImages']}
     257                #For get the description of an app we must go to a specific url.
     258                #$(appname) we'll be replaced with the appname so the url matches the right one.
     259                #If other site has other url naming convention it'll be mandatory to define it with the appropiate replacements
     260                infoList={'appimg':'https://bintray.com/probono/AppImages/$(appname)'}
    244261                self.descDict={}
    245                 for repo in repolist:
    246                         self._debug(("Fetching repo %s")%(repo))
    247                         print ("Download Progress: "+progressBar,end="\r")
    248                         progressBar=progressBar+"#"
    249                         applist=self._generate_applist(self._fetch_repo(repo))
    250                         print ("Download Progress: "+progressBar,end="\r")
    251                         self._debug("Processing info...")
    252                         self._th_generate_xml_catalog(applist,outdir,progressBar)
    253                         self._debug("Fetched repo "+repo)
    254                 self._debug("Setting status to 0")
    255                 self._set_status(0)
    256                 return("Repo fetched")
     262#               if not self._clear_bundle_files(outdir):
     263#                       self._debug("Unable to clear bundles dir "+outdir)
     264#                       return(False)
     265
     266                for repoType,repoTypeList in repoList.items():
     267                        infoPage=infoList[repoType]
     268                        outdir=self.bundleDir+'/'+repoType+'/'
     269                        self._chk_bundle_dir(outdir)
     270                        for repo in repoTypeList:
     271                                self._debug(("Fetching repo %s")%(repo))
     272                                print (_("Fetching %s catalogue: "+progressBar)%repoType,end="\r")
     273                                progressBar=progressBar+"#"
     274                                print (_("Fetching %s catalogue: "+progressBar)%repoType,end="\r")
     275                                applist=self._generate_applist(self._fetch_repo(repo))
     276                                progressBar=progressBar+"##"
     277                                print (_("Fetching %s catalogue: "+progressBar)%repoType,end="\r")
     278                                self._debug("Processing info...")
     279                                self._th_generate_xml_catalog(applist,outdir,infoPage,repoType,progressBar)
     280                                self._debug("Fetched repo "+repo)
     281                return(True)
     282
     283        def _chk_bundle_dir(self,outdir):
     284                msg_status=True
     285                if not os.path.isdir(outdir):
     286                        try:
     287                                os.makedirs(outdir)
     288                        except:
     289                                msg_status=False
     290                return(msg_status)
    257291
    258292        def _fetch_repo(self,repo):
    259                 with urllib.request.urlopen('https://dl.bintray.com/probono/AppImages') as f:
     293                with urllib.request.urlopen(repo) as f:
    260294                        content=(f.read().decode('utf-8'))
    261295                return(content)
     
    271305                return(applist)
    272306
    273         def _get_description(self,appName):
     307        def _get_description(self,appName,infoPage):
    274308                desc=''
    275                 self._debug("Getting description from 'https://bintray.com/probono/AppImages/'"+appName)
     309                if '$(appname)' in infoPage:
     310                        infoPage=infoPage.replace('$(appname)',appName)
     311                self._debug("Getting description from "+infoPage)
    276312                try:
    277                         with urllib.request.urlopen('https://bintray.com/probono/AppImages/'+appName) as f:
     313                        with urllib.request.urlopen(infoPage) as f:
    278314                                content=(f.read().decode('utf-8'))
    279315                                soup=BeautifulSoup(content,"html.parser")
     
    287323                return(desc)
    288324
    289         def _th_generate_xml_catalog(self,applist,outdir,progressBar=''):
     325        def _th_generate_xml_catalog(self,applist,outdir,infoPage,repoType,progressBar=''):
    290326                CURSOR_UP='\033[F'
    291327                ERASE_LINE='\033[K'
     
    297333                random.shuffle(randomList)
    298334                lenAppList=len(randomList)
    299                 inc=25/lenAppList
     335                inc=30/lenAppList
     336                print (CURSOR_UP)
    300337                for app in randomList:
    301                         th=threading.Thread(target=self._th_write_xml, args = (app,outdir,semaphore,inc))
     338                        th=threading.Thread(target=self._th_write_xml, args = (app,outdir,infoPage,semaphore,inc))
    302339                        th.start()
    303 #               while (len(threading.enumerate())>3):
    304 #                       self._callback()
    305                         time.sleep(0.5)
    306                         progressBar=self.progress
    307                         print ("Download Progress: "+str(int(progressBar))+"%",end="\r")
    308 
    309         def _th_write_xml(self,app,outdir,semaphore,inc):
     340                os.system('setterm -cursor off')
     341                while threading.active_count()>2: #Discard both main and own threads
     342                        for i in range(len(progressBar),int(self.progress)):
     343                                progressBar='#'+progressBar
     344#                       print (CURSOR_UP)
     345                        print (_("Fetching %s catalogue: "+progressBar)%repoType,end="\r")
     346                os.system('setterm -cursor on')
     347                print('')
     348
     349        def _th_write_xml(self,app,outdir,infoPage,semaphore,inc):
    310350                semaphore.acquire()
    311351                lock=threading.Lock()
    312                 self._debug("Generating "+app+" xml")
    313352                nameSplitted=app.split('-')
    314353                name=nameSplitted[0]
    315354                version=nameSplitted[1]
    316355                arch=nameSplitted[2]
    317                 f=open(outdir+'/'+name+"_"+version+".appdata.xml",'w')
    318                 f.write('<?xml version="1.0" encoding="UTF-8"?>'+"\n")
    319                 f.write("<components version=\"0.10\">\n")
    320                 f.write("<component  type=\"desktop-application\">\n")
    321                 f.write("  <id>"+app.lower()+"</id>\n")
    322                 f.write("  <pkgname>"+app+"</pkgname>\n")
    323                 f.write("  <name>"+name+"</name>\n")
    324                 f.write("  <summary>"+name+" AppImage Bundle</summary>\n")
    325                 f.write("  <metadata_license>CC0-1.0</metadata_license>\n")
    326                 f.write("  <provides><binary>"+app+"</binary></provides>\n")
    327                 f.write("  <releases>\n")
    328                 f.write("  <release version=\""+version+"\" timestamp=\"1408573857\"></release>\n")
    329                 f.write("  </releases>\n")
    330                 f.write("  <launchable type=\"desktop-id\">"+name+".desktop</launchable>\n")
     356                filename=outdir+name+"_"+version+".appdata.xml"
     357                self._debug("checking if we need to download "+filename)
     358                if not os.path.isfile(filename):
     359                        self._debug("Generating "+app+" xml")
     360                        f=open(filename,'w')
     361                        f.write('<?xml version="1.0" encoding="UTF-8"?>'+"\n")
     362                        f.write("<components version=\"0.10\">\n")
     363                        f.write("<component  type=\"desktop-application\">\n")
     364                        f.write("  <id>"+app.lower()+"</id>\n")
     365                        f.write("  <pkgname>"+app+"</pkgname>\n")
     366                        f.write("  <name>"+name+"</name>\n")
     367                        f.write("  <summary>"+name+" AppImage Bundle</summary>\n")
     368                        f.write("  <metadata_license>CC0-1.0</metadata_license>\n")
     369                        f.write("  <provides><binary>"+app+"</binary></provides>\n")
     370                        f.write("  <releases>\n")
     371                        f.write("  <release version=\""+version+"\" timestamp=\"1408573857\"></release>\n")
     372                        f.write("  </releases>\n")
     373                        f.write("  <launchable type=\"desktop-id\">"+name+".desktop</launchable>\n")
     374                        with lock:
     375                                if name in self.descDict.keys():
     376                                        description=self.descDict[name]
     377                                else:
     378                                        description=self._get_description(name,infoPage)
     379                                        self.descDict.update({name:description})
     380                        f.write("  <description><p>This is an AppImage bundle of app "+name+". It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully.</p><p>"+description+"</p></description>\n")
     381                        f.write("  <bundle type=\"appimage\">"+app+"</bundle>\n")
     382                        f.write("  <keywords>\n")
     383                        f.write("       <keyword>"+name+"</keyword>\n")
     384                        f.write("       <keyword>appimage</keyword>\n")
     385                        f.write("  </keywords>\n")
     386                        f.write("  <categories>\n")
     387                        f.write("       <category>AppImage</category>\n")
     388                        f.write("       <category>GTK</category>\n")
     389                        f.write("  </categories>\n")
     390                        f.write("<icon type=\"cached\">"+name+"_"+name+".png</icon>\n")
     391                        f.write("</component>\n")
     392                        f.write("</components>\n")
     393                        f.close()
    331394                with lock:
    332                         if name in self.descDict.keys():
    333                                 description=self.descDict[name]
    334                         else:
    335                                 description=self._get_description(name)
    336                                 self.descDict.update({name:description})
    337395                        self.progress=self.progress+inc
    338                 f.write("  <description><p>This is an AppImage bundle of app "+name+". It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully.</p><p>"+description+"</p></description>\n")
    339                 f.write("  <bundle type=\"appimage\">"+app+"</bundle>\n")
    340                 f.write("  <keywords>\n")
    341                 f.write("       <keyword>"+name+"</keyword>\n")
    342                 f.write("       <keyword>appimage</keyword>\n")
    343                 f.write("  </keywords>\n")
    344                 f.write("  <categories>\n")
    345                 f.write("       <category>AppImage</category>\n")
    346                 f.write("       <category>GTK</category>\n")
    347                 f.write("  </categories>\n")
    348                 f.write("<icon type=\"cached\">"+name+"_"+name+".png</icon>\n")
    349                 f.write("</component>\n")
    350                 f.write("</components>\n")
    351                 f.close()
    352396                semaphore.release()
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/storeManager.py

    r5188 r5199  
    152152                                if sw_withoutStatus:
    153153                                        self.result[action]['status']={'status':0,'msg':''}
    154                                         self.extraActions.update({action:1})
    155154                                else:
    156155                                        self.result[action]['status']={'status':-1,'msg':''}
     
    372371                action='load'
    373372                loadFunction=self._execute_class_method(action)
    374                 print(self.loadBundles)
    375373                self.store=loadFunction.execute_action(action,self.store,self.loadBundles)
    376374        #def _load_Store
Note: See TracChangeset for help on using the changeset viewer.