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

Adds support for .AppImage and implements parsing for .desktop #10

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

xaoseric
Copy link

Adds support for .AppImage files and parses .desktop files with QSettings

@xaoseric
Copy link
Author

134d3c379dae24472ad50ebe41b74921
Verified that parsing of .desktop files works as well.

@xaoseric
Copy link
Author

46cf4dae5fafb463feb82507caa98be8
And one showing a Discord appimage working properly

@probonopd
Copy link
Member

Thanks @xaoseric.
Shouldn't we also parse the Name= key and make it possible to e.g., launch Discord even though the file name is Discord-3.1.0alpha3.git-hf876-x86_64.AppImage? No one wants to type Discord-3.1.0alpha3.git-hf876-x86_64. Then the question is, if there is Discord-3.1.0alpha3.git-hf876-x86_64.AppImage and Discord-3.2.0beta4_x86_64.AppImage, which one should be started by launch Discord? The one with the greater version, as in the (optional) X-AppImage-Version key in the .desktop file.

@xaoseric
Copy link
Author

xaoseric commented Mar 14, 2021

Ideally the Exec= which we parse in .desktop files would point to the correct executable. Looking for Name= and X-AppImage-Version= in .desktop could be a good option if it has a "-" in it, the goal was to get it working with Discord.AppImage for the moment so we can go back and add to it later.

The best solution would be a multi platform app store that could download .AppImage, .app and .AppDir files automatically and keep them updated in /Applications, /System and /Library.

One small bug I did find is that if we do launch PyCharm CE it says that it can't find PyCharm. We need to do launch "PyCharm CE" for it to find that .app directory.

@probonopd
Copy link
Member

probonopd commented Mar 14, 2021

Ideally the Exec= which we parse in .desktop files would point to the correct executable.

This is not how AppImage works. What do you mean by "the correct executable"? The "correct executable" is the AppImage itself.

"TODO: Parse it for Exec="

Why do you want to do that? This key has no useful information for how the AppImage should be launched. Only the path to the AppImage is needed for that.

@probonopd
Copy link
Member

probonopd commented Mar 14, 2021

if (file.fileName() == firstArg + ".desktop")

I think this is not what we should be checking for. Instead, we should be checking whether Name= matches.

Example:

launch Discord

should check if we have Name=Discord in the desktop file. If yes, then it is a candidate.

But to check this, we would need to have a way to peek inside the AppImage to read the desktiop file, wouldn't we?

@xaoseric
Copy link
Author

xaoseric commented Mar 14, 2021

"TODO: Parse it for Exec="

Why do you want to do that? This key has no useful information for how the AppImage should be launched. Only the path to the AppImage is needed for that.

Exec= points to the executble which allows none .app, .AppDir and .AppImage files to work ex: for Firefox it points to /usr/local/bin/firefox and it was what was in the todo notes before since we already check for the .AppImage extension before checking if a .desktop is a candidate.

if (file.fileName() == firstArg + ".desktop")

I think this is not what we should be checking for. Instead, we should be checking whether Name= matches.

Example:

launch Discord

should check if we have Name=Discord in the desktop file. If yes, then it is a candidate.

But to check this, we would need to have a way to peek inside the AppImage to read the desktiop file, wouldn't we?

Yes, we should also check that Name= also matches if the .desktop matches which at this point in parsing .desktop files, we are just parsing those directly so no need to look inside of any file.

As far as looking inside the AppImage, we could use libappimage to do that or we implement our own way of doing that which I think would probably be further down the line once we get the core functionality of it working we can go back and add in additional features like that.

https://docs.appimage.org/api/libappimage/

As it is on Linux, as long as it is executable, we don’t have to do anything on our end unless we want to check the .desktop file in the .AppImage.

For FreeBSD however, that is another matter:
https://forums.freebsd.org/threads/appimage-support.75097/

@probonopd
Copy link
Member

probonopd commented Mar 14, 2021

Exec= points to the executble which allows none .app, .AppDir and .AppImage files to work

I think you don't understand how AppImages work. To launch an AppImage, you need to use the path to the AppImage, whereas the Exec= key contains the name and arguments of the executable that in turn get used inside the AppImage (if the AppRun in that particular AppImage uses this information at all).

So, to launch an AppImage from the outside world, all you need to know is the path to the AppImage.

My objective is to do away with .desktop files altogether.

Shouldn't we also parse the Name= key and make it possible to e.g., launch Discord even though the file name is Discord-3.1.0alpha3.git-hf876-x86_64.AppImage? No one wants to type Discord-3.1.0alpha3.git-hf876-x86_64.

So thinking about it again maybe we could do something much simpler which would cover at least >80% of cases:

  1. Look for files with the .AppImage suffix
  2. If there are at least 2 - characters in the filename, remove everything behind the second-last - character from the filename
  3. there is only one - character in the filename, remove everything behind the -
  4. Replace _ with
  5. Compare the result against what the user wants to launch to determine whether we have a candidate
  6. If there are at least 2 - characters in the filename, assume that what is between the first and second - is the version; this will be needed to decide amongst several candidates (to pick the latest version)

Result:

launch Discord would work with, e.g.,

  • Discord-1.3.0beta1-x86_64.AppImage
  • Discord-1.3.0beta1.AppImage
  • Discord.AppImage

But it would fail on

  • Discord-1.3.0-beta1-x86_64.AppImage

launch "Discord Beta" would work with, e.g.,

  • Discord_Beta-1.3.0beta1-x86_64.AppImage
  • Discord_Beta-1.3.0beta1.AppImage
  • Discord_Beta.AppImage

But it would fail on

  • Discord_Beta-1.3.0-beta1-x86_64.AppImage

@xaoseric
Copy link
Author

I think you don't understand how AppImages work. To launch an AppImage, you need to use the path to the AppImage, whereas the Exec= key contains the name and arguments of the executable that in turn get used inside the AppImage (if the AppRun in that particular AppImage uses this information at all).

A .AppImage is an executable on Linux. Quoting the faq from the docs. https://docs.appimage.org/user-guide/faq.html#question-how-do-i-run-an-appimage

How do I run an AppImage?
Make it executable and double-click it.

So what we would need to do is check if we are running on BSD or Linux, if it is running on a BSD based system we can than implement any compatibility that needs to be done to make it work.

According the AppImage spec repo, there is an AppRun contained in the root of the filesystem image, supporting type 2 onward would make the most sense.

https://github.com/AppImage/AppImageSpec/blob/master/draft.md#type-2-image-format

So thinking about it again maybe we could do something much simpler which would cover at least >80% of cases:

  1. Look for files with the .AppImage suffix
  2. If there are at least 2 - characters in the filename, remove everything behind the second-last - character from the filename
  3. there is only one - character in the filename, remove everything behind the -
  4. Replace _ with
  5. Compare the result against what the user wants to launch to determine whether we have a candidate
  6. If there are at least 2 - characters in the filename, assume that what is between the first and second - is the version; this will be needed to decide amongst several candidates (to pick the latest version)

Yes, that is a good idea, that can be a feature enhancement further on down the line now that we know we have something that is working.

@xaoseric
Copy link
Author

Opened an issue referencing the improvements for the AppImage handling so we can get this merged in and discuss how we want to improve it in that issue.

@probonopd
Copy link
Member

probonopd commented Mar 14, 2021

So what we would need to do is check if we are running on BSD or Linux, if it is running on a BSD based system we can than implement any compatibility that needs to be done to make it work.

Yes, that is being discussed at AppImage/AppImageKit#98.
But that whole topic is more complex.
Don't worry about Linux AppImages on FreeBSD yet.
Work is underway.

Let's make this issue here only about finding and launching the correct AppImage.

So thinking about it again maybe we could do something much simpler which would cover at least >80% of cases: (...)

Yes, that is a good idea, that can be a feature enhancement further on down the line

Do you think you can make it part of this PR?

@xaoseric
Copy link
Author

xaoseric commented Mar 14, 2021

Do you think you can make it part of this PR?

Yes, certainly will try.

Detects new version if more than one file exists
@xaoseric
Copy link
Author

@probonopd the PR now supports the changes as requested.

@probonopd
Copy link
Member

Thank you very much. Looks promising.
However I am running into a segfault. I created three files with this content and made them executable:

#!/bin/sh

echo "This works" > /dev/stderr
exit 1
  • ~/Applications/Test.AppImage
  • ~/Applications/Test-2.0.AppImage
  • ~/home/user/Applications/Test-3.0.AppImage

Then ran:

% ./launch Test
# Found "/home/user/Applications/Test-3.0.AppImage"
# Found "/home/user/Applications/Test.AppImage"
# Found "/home/user/Applications/Test-2.0.AppImage"
(...)
Took 16 milliseconds to find candidates via the filesystem
Candidates: (QFileInfo(/home/user/Applications/Test-3.0.AppImage), QFileInfo(/home/user/Applications/Test.AppImage), QFileInfo(/home/user/Applications/Test-2.0.AppImage))
0
zsh: segmentation fault  ./launch Test

Possibly it doesn't know what to do when some candidates have a version and some don't. In those situations, it should use the one with the highest version number, in this example ~/home/user/Applications/Test-3.0.AppImage.

@xaoseric
Copy link
Author

xaoseric commented Mar 15, 2021

Awesome, so it is getting closer to being on the right track then, once we get it working, the same concept should work for .app and .AppDir files. You could probably merge the stuff into a develop branch so that way the changes don't affect the stable main branch, and once there is enough changes to warrant a new release, we can merge into the master. Next thing we probably will want to do is create some type of database for keeping track of the available apps so doing say "launch --scan" would scan the system for available apps and add them to a database.

@probonopd
Copy link
Member

probonopd commented Apr 2, 2021

% ./launch Test
# Descending into "/Applications/Developer"
# Descending into "/Applications/Video"
# Descending into "/Applications/Autostart"
# Descending into "/Applications/Preferences"
# Descending into "/Applications/Graphics"
# Descending into "/Applications/Games"
# Descending into "/Applications/Utilities"
# Descending into "/Applications/Audio"
# Descending into "/Applications/Developer Preview"
# Descending into "/Applications/3D Printing"
Took 17 milliseconds to find candidates via the filesystem
Candidates: ()

% LANG=C ls -lh ~/Applications/Test*
-rwxr-xr-x  1 user  user    50B Mar 15 19:54 /home/user/Applications/Test-2.0.AppImage
-rwxr-xr-x  1 user  user    50B Mar 15 19:54 /home/user/Applications/Test-3.0.AppImage
-rwxr-xr-x  1 user  user    50B Mar 15 19:54 /home/user/Applications/Test.AppImage

% cat /home/user/Applications/Test.AppImage
#!/bin/sh

echo "This works" > /dev/stderr
exit 1

Why does it not find them?

@xaoseric
Copy link
Author

@probonopd reverted back to old if statement, should be fixed now.

@probonopd
Copy link
Member

probonopd commented Apr 19, 2021

Hello @xaoseric, it now identifies the candidates correctly but segfaults while trying to decide which one to use:

FreeBSD% ./launch Test
# Found "/home/user/Applications/Test-2.0.AppImage"
# Found "/home/user/Applications/Test.AppImage"
# Found "/home/user/Applications/Test-3.0.AppImage"
# Descending into "/Applications/Video"
# Descending into "/Applications/Developer"
# Descending into "/Applications/Autostart"
# Descending into "/Applications/3D Printing"
# Descending into "/Applications/Utilities"
# Descending into "/Applications/Audio"
# Descending into "/Applications/Office"
# Descending into "/Applications/Developer Preview"
# Descending into "/Applications/Preferences"
# Descending into "/Applications/Graphics"
Took 13 milliseconds to find candidates via the filesystem
Candidates: (QFileInfo(/home/user/Applications/Test-2.0.AppImage), QFileInfo(/home/user/Applications/Test.AppImage), QFileInfo(/home/user/Applications/Test-3.0.AppImage))
QFileInfo(/home/user/Applications/Test-2.0.AppImage)
0
zsh: segmentation fault  ./launch Test

Note that in my case /home/user/Applications/Test-2.0.AppImage is not really an AppImage, but I doubt it would make any difference?

FreeBSD% file /home/user/Applications/Test-2.0.AppImage
/home/user/Applications/Test-2.0.AppImage: POSIX shell script, ASCII text executable

The expected behavior would be that it recognizes that 3.0 is the highest version number among the three candidates and hence selects that candidate.

@xaoseric
Copy link
Author

Odd, it correctly identifies the new version on my linux setup, could it be a difference between BSD and Linux in the way that Qt handles things?

@probonopd
Copy link
Member

Possible. Any way you could download a helloSystem ISO and test it there?

@xaoseric
Copy link
Author

I'll be setting up a test system with helloSystem this weekend.

@probonopd
Copy link
Member

Hello @xaoseric how did your tests go?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants