Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Files checked in for AppDirAssistant. #17

Merged
merged 1 commit into from
Mar 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added AppDirAssistant.AppDir/.DirIcon
Binary file not shown.
6 changes: 6 additions & 0 deletions AppDirAssistant.AppDir/appimager.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[Desktop Entry]
Type=Application
Name=AppDirAssistant
Exec=appimager
Icon=appimager
Categories=Development;
Binary file added AppDirAssistant.AppDir/appimager.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 70 additions & 0 deletions AppDirAssistant.AppDir/usr/bin/AppImageKit/AppDir.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/python

# probono 11-2010

import os, sys

sys.path.append(os.path.dirname(os.path.dirname(__file__))) # One directory up
import timesavers # Needs to be bundled


# To be implemented:
#
# Check whether AppDir is valid
# - Check whether AppRun is present and executable
# - Check whether .desktop file is present and Exec and Icon can be found
#
# Find Exec
#
# Find Icon
#
# Make new AppDir from template
#
# Check whether /usr is patched
# Check whether /etc is patched
#
# Run the app
# ldd the app
#
# Package the AppDir as an AppImage
#

class AppDir(object):

def __init__(self, path):
self.path = path

def patch_usr(self):
command = 'find "%s"/*/ -type f -exec sed -i -e "s|/usr|././|g" {} \\;' % (self.path)
timesavers.run_shell_command(command)

def patch_etc(self):
command = 'find "%s"/*/ -type f -exec sed -i -e "s|/etc|./et|g" {} \\;' % (self.path)
timesavers.run_shell_command(command)
command = 'cd "%s/usr" ; ln -s ../etc ./et ; cd -' % (self.path)
timesavers.run_shell_command(command)

def patch(self):
self.patch_usr()
self.patch_etc()

def insert_apprun(self):
print("FIXME: To be done properly")
command = 'cp ../AppRun "%s/"' % (self.path)
timesavers.run_shell_command(command)

def insert_desktop(self, name="dummy"):
f = open(self.path + "/" + name + ".desktop", "w")
f.write("[Desktop Entry]\n")
f.write("Type=Application\n")
f.write("Icon=%s\n" % (name))
f.write("Name=%s\n" % (name.capitalize()))
f.write("Exec=%s\n" % (name))
f.close

def __repr__(self):
return "<AppDir at %s>" % (self.path)

if __name__ == "__main__":
A = AppDir("/some")
print A
Binary file not shown.
174 changes: 174 additions & 0 deletions AppDirAssistant.AppDir/usr/bin/AppImageKit/AppImage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#!/usr/bin/env python


# probono 11-2010


import os, sys, subprocess, hashlib, urllib, tempfile, shutil
from locale import normalize

sys.path.append(os.path.dirname(os.path.dirname(__file__))) # One directory up

import timesavers, xxdg.DesktopEntry, xxdg.BaseDirectory # Needs to be bundled


#
# Helper functions
#


def get_appimages_in_dir(directory):
"Returns a list of all AppImages in a given directory and its subdirectories"
list = []
files = timesavers.run_shell_command("find '" + directory + "'")
for file in files:
AI = AppImage(file)
#AIL = AppImage(os.path.realpath(file)) # follow symlinks
if AI.check_whether_is_appimage() == True:
list.append(AI)
return list


#
# Classes
#


class AppImage:

def __init__(self, path):
self.path = os.path.normpath(os.path.abspath(path))
self.path_md5 = hashlib.md5('file://' + urllib.quote(self.path)).hexdigest()
self.is_appimage = False
self.iconfile_path = os.path.expanduser('~/.thumbnails/normal/') + self.path_md5 + '.png'
desktopfiles_location = xxdg.BaseDirectory.xdg_data_home + "/applications/appimage/"
self.desktopfile_path = desktopfiles_location + self.path_md5 + ".desktop" # TODO: factor out

def check_whether_is_appimage(self):
"Checks whether the file is an AppImage. TODO: Speed up by not using file"
type = timesavers.run_shell_command("file -k '" + os.path.realpath(self.path) + "' | grep 'executable' | grep 'ISO 9660'") # follow symlinks
if type != None:
self.is_appimage = True
return True
else:
return False

def get_file(self, filepath, destination=None):
"Returns the contents of a given file as a variable"
command = "'cmginfo' -f '/" + self.path + "' -e '" + filepath + "'"
result = timesavers.run_shell_command(command, False)
if result != "":
return result
else:
return None

def get_desktop_filename(self, destination=None):
command = "'cmginfo' -l / -f '" + self.path + "'"
toplevel_files = timesavers.run_shell_command(command)
for toplevel_file in toplevel_files:
if ".desktop" in toplevel_file:
return toplevel_file

def get_icon_filename(self, destination=None):
return "/.DirIcon" # Could become more elaborate


def get_file_list(self):
command = "'cmginfo' '/" + self.path + "'"
return timesavers.run_shell_command(command)

def install_desktop_integration(self, parentifthreaded=None):
if not os.path.exists(self.iconfile_path): # Don't overwrite if it already exists
try: os.makedirs(os.path.dirname(self.iconfile_path))
except: pass
print "* Installing %s" % (self.iconfile_path)
f = open(self.iconfile_path, "w")
f.write(self.get_file("/.DirIcon"))
f.close()
if not os.path.exists(self.desktopfile_path): # Don't overwrite if it already exists, as this triggers cache rebuild
try: os.makedirs(os.path.dirname(self.desktopfile_path))
except: pass
print "* Installing %s" % (self.desktopfile_path)
#f = open(desktopfile_path, "w")
f = tempfile.NamedTemporaryFile(delete=False)
f.write(self.get_file(self.get_desktop_filename()))
f.close()
desktop = xxdg.DesktopEntry.DesktopEntry()
desktop.parse(f.name)
desktop.set("X-AppImage-Original-Exec", desktop.get("Exec"))
desktop.set("X-AppImage-Original-Icon", desktop.get("Icon"))
try:
if desktop.get("TryExec"):
desktop.set("X-AppImage-Original-TryExec", desktop.get("TryExec"))
desktop.set("TryExec", self.path) # Definitely quotes are not accepted here
except:
pass
desktop.set("Icon", self.iconfile_path)
desktop.set("X-AppImage-Location", self.path)
desktop.set("Type", "Application") # Fix for invalid .desktop files that contain no Type field
desktop.set("Exec", '"' + self.path + '"') # Quotes seem accepted here but only one % argument????
# desktop.validate()
desktop.write(f.name)
os.chmod(f.name, 0755)
print self.desktopfile_path
shutil.move(f.name, self.desktopfile_path) # os.rename fails when tmpfs is mounted at /tmp
if os.env("KDE_SESSION_VERSION") == "4":
timesavers.run_shell_command("kbuildsycoca4") # Otherwise KDE4 ignores the menu

def uninstall_desktop_integration(self):
if os.path.isfile(self.desktopfile_path):
try:
os.unlink(self.desktopfile_path)
print "* Removed %s" % (self.desktopfile_path)
except:
print "* Failed to remove %s" % (self.desktopfile_path)
if os.path.isfile(self.iconfile_path):
try:
os.unlink(self.iconfile_path)
print "* Removed %s" % (self.iconfile_path)
except:
print "* Failed to remove %s" % (self.iconfile_path)

def extract(self, destination_dir="/tmp"):
dest_dir = os.path.join(destination_dir, os.path.basename(self.path).replace(".AppImage","") + ".AppDir")
# subprocess.call("xorriso", "-indev", self.path, "-osirrox", "on", "-extract", "/", destination_dir)
# xorriso -indev "${1}" -osirrox on -extract / $HOME/Desktop/"${NAME}.AppDir"
# sudo chown -R "${USER}" $HOME/Desktop/"${NAME}.AppDir"
# sudo chmod -R u+w $HOME/Desktop/"${NAME}.AppDir"
# print dirname
print "To be implemented - looks like cmginfo can't extract whole images?"

def set_executable_bit(self, boolean):
# Ideally, we would try whether we can ask the user via a gtk.MESSAGE_WARNING
# but that seems to be complicated to do without freezing the daemon (threading is tough to get right)
if boolean == True:
timesavers.run_shell_command("chmod a+x '" + self.path + "'")
else:
timesavers.run_shell_command("chmod a-x '" + self.path + "'")

def __repr__(self):
if self.is_appimage:
existing = "Existing "
else:
existing = ""
return "<%sAppImage %s>" % (existing, self.path)


def main():
print "\nChecking /Applications for AppImages..."
appimages = get_appimages_in_dir("/Applications/")
for ai in appimages:
print ai
#thread.start_new_thread(ai.install_desktop_integration,(1,))
ai.install_desktop_integration()
# print "\nListing files in %s..." % (str(appimages[0]))
# print appimages[0].get_file_list()
# print "\nExtracting AppRun from %s..." % (str(appimages[0]))
# print appimages[0].get_file("/AppRun")
# print "\nExtracting desktop file from %s..." % (str(appimages[0]))
# print appimages[0].get_file(appimages[0].get_desktop_filename())
# appimages[0].install_desktop_integration()
#appimages[0].extract()

if __name__ == "__main__":
main()
Empty file.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions AppDirAssistant.AppDir/usr/bin/AppImageKit/bin/strace
Binary file not shown.
Binary file not shown.
Binary file not shown.
32 changes: 32 additions & 0 deletions AppDirAssistant.AppDir/usr/bin/AppImageKit/timesavers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python

# probono 11-2010

import os, sys

# Make external binaries and their libs available if they are privately bundled
ldp = os.environ.get("LD_LIBRARY_PATH")
p = os.environ.get("PATH")
if ldp == None: ldp = ""
if p == None: p = ""
binpath = os.path.join(os.path.dirname(__file__), "bin")
ld_library_path = os.path.join(os.path.dirname(__file__), "lib")
os.environ.update({"PATH": binpath + ":" + p})
os.environ.update({"LD_LIBRARY_PATH": ld_library_path + ":" + ldp})

def run_shell_command(command, lines_as_list=True):
"Runs a command like in a shell, including | and returns the resulting lines"
# print "Running command: %s" % (command)
if lines_as_list == True:
list = os.popen(command).read().split("\n")
del list[-1] # Remove last newline
else:
list = os.popen(command).read() # Not really a list in this case
# Need to remove last newline?
if list == []:
return None
else:
return list

if __name__ == "__main__":
print run_shell_command("ls -l / | grep root")
Binary file not shown.
97 changes: 97 additions & 0 deletions AppDirAssistant.AppDir/usr/bin/AppImageKit/xxdg/BaseDirectory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""
This module is based on a rox module (LGPL):

http://cvs.sourceforge.net/viewcvs.py/rox/ROX-Lib2/python/rox/basedir.py?rev=1.9&view=log

The freedesktop.org Base Directory specification provides a way for
applications to locate shared data and configuration:

http://standards.freedesktop.org/basedir-spec/

(based on version 0.6)

This module can be used to load and save from and to these directories.

Typical usage:

from rox import basedir

for dir in basedir.load_config_paths('mydomain.org', 'MyProg', 'Options'):
print "Load settings from", dir

dir = basedir.save_config_path('mydomain.org', 'MyProg')
print >>file(os.path.join(dir, 'Options'), 'w'), "foo=2"

Note: see the rox.Options module for a higher-level API for managing options.
"""

from __future__ import generators
import os

_home = os.environ.get('HOME', '/')
xdg_data_home = os.environ.get('XDG_DATA_HOME',
os.path.join(_home, '.local', 'share'))

xdg_data_dirs = [xdg_data_home] + \
os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':')

xdg_config_home = os.environ.get('XDG_CONFIG_HOME',
os.path.join(_home, '.config'))

xdg_config_dirs = [xdg_config_home] + \
os.environ.get('XDG_CONFIG_DIRS', '/etc/xdg').split(':')

xdg_cache_home = os.environ.get('XDG_CACHE_HOME',
os.path.join(_home, '.cache'))

xdg_data_dirs = filter(lambda x: x, xdg_data_dirs)
xdg_config_dirs = filter(lambda x: x, xdg_config_dirs)

def save_config_path(*resource):
"""Ensure $XDG_CONFIG_HOME/<resource>/ exists, and return its path.
'resource' should normally be the name of your application. Use this
when SAVING configuration settings. Use the xdg_config_dirs variable
for loading."""
resource = os.path.join(*resource)
assert not resource.startswith('/')
path = os.path.join(xdg_config_home, resource)
if not os.path.isdir(path):
os.makedirs(path, 0700)
return path

def save_data_path(*resource):
"""Ensure $XDG_DATA_HOME/<resource>/ exists, and return its path.
'resource' is the name of some shared resource. Use this when updating
a shared (between programs) database. Use the xdg_data_dirs variable
for loading."""
resource = os.path.join(*resource)
assert not resource.startswith('/')
path = os.path.join(xdg_data_home, resource)
if not os.path.isdir(path):
os.makedirs(path)
return path

def load_config_paths(*resource):
"""Returns an iterator which gives each directory named 'resource' in the
configuration search path. Information provided by earlier directories should
take precedence over later ones (ie, the user's config dir comes first)."""
resource = os.path.join(*resource)
for config_dir in xdg_config_dirs:
path = os.path.join(config_dir, resource)
if os.path.exists(path): yield path

def load_first_config(*resource):
"""Returns the first result from load_config_paths, or None if there is nothing
to load."""
for x in load_config_paths(*resource):
return x
return None

def load_data_paths(*resource):
"""Returns an iterator which gives each directory named 'resource' in the
shared data search path. Information provided by earlier directories should
take precedence over later ones."""
resource = os.path.join(*resource)
for data_dir in xdg_data_dirs:
path = os.path.join(data_dir, resource)
if os.path.exists(path): yield path
Binary file not shown.
Loading