Git Product home page Git Product logo

antony-jr / qappimageupdate Goto Github PK

View Code? Open in Web Editor NEW
28.0 7.0 13.0 4.31 MB

Qt5 library and plugin for updating AppImages. :heart:

Home Page: https://antony-jr.github.io/QAppImageUpdate

License: BSD 3-Clause "New" or "Revised" License

C++ 91.92% CMake 1.84% JavaScript 4.36% CSS 0.08% QMake 1.23% Shell 0.57%
appimage qt5 bridge autoupdate easy-to-use updater library small zsync appimage-updater-bridge

qappimageupdate's Introduction

QAppImageUpdate GitHub issues GitHub stars GitHub license Codacy Badge Test and Deploy

Note: QAppImageUpdate was formerly known as "AppImage Updater Bridge". As of v2.0.0 of the project, it is now known as QAppImageUpdate with breaking changes to everything. So if you want to use v1.x, you can use the git tag v1.1.9 which is latest version of v1.x

QAppImageUpdate is a delta updater based on the zsync algorithm for the AppImage format, Using this library you can delta update any AppImage file, That is, Only download the binary data which you need to get the latest version, Therefore saving your time and internet.

QAppImageUpdate is not the official library to do this stuff, The official library is here which is also written in C++ but with no real Qt support , Thats why this library is built.

This library gives absolute support for Qt, Infact, All you need is the minimal installation of Qt(i.e, base).

Features

  • Single Threaded , Non-Blocking API - Using Qt's Event Loop.(Optionally , You can use a seperate thread.)

  • Easy to Use API - Made some effort to match Qt's style.

  • Cyclic and Async API - The whole library is fully cyclic and Async.(Only signals and slots.)

  • Pure C++ - Ported most of the legacy Zsync code to C++.

  • No third party libraries needed - The reason why you want to use this library.

  • Drink the Qt Kool-aid - In a positive way.

  • Optional Decentralized Update with BitTorrent Protocol - Reduce load on server.

Witness it with your own eyes,

#include <QCoreApplication>
#include <QAppImageUpdate>

int main(int argc, char **argv) 
{
    QCoreApplication app(argc, argv);
    QAppImageUpdate updater;

    QObject::connect(&updater, &QAppImageUpdate::finished, 
		      &app, &QCoreApplication::quit);
    
    updater.setShowLog(true);
    updater.start();
    return app.exec();
}

Try it

See this library in action at this repo which reimplements the official AppImageUpdater Tool using this library.

Getting Started

For Documentation on old versions, See Documentation Versions.

Please refer the official Documentation.

Contributors Contributors


technic93
💻

Lukas Werling
💻

Alexis López Zubieta
💻

probonopd
💻

Friedrich
💻

Acknowledgements Thank You

Support Twitter

If you think that this project is cool then you can give it a ⭐ or 🍴 it if you want to improve it with me. I really ❤️ stars though!

License

The BSD 3-clause "New" or "Revised" License.

Copyright (C) 2017-2020, Antony jr.
All Rights Reserved.

qappimageupdate's People

Contributors

antony-jr avatar azubieta avatar kossebau avatar lluchs avatar probonopd avatar technic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

qappimageupdate's Issues

migrate from QThread inherited to worker model

Currently implementation is directly using QThread by inheriting it , This is not a very good practice , so this has to be migrated to worker model soon. The library seems to make a crash.

remove deprecated `register` keyword

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue: AFAIK Nobody needs it in today's compilers and it is deprecated since C++11.

Fatal flaw

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:

This is a very serious issue which should be fixed asap , this bridge does not use the seed files and thus downloads all data without delta transfer.

Ways to Reproduce the issue (optional):
Use AppImageUpdater

Static analyzer checks

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:

  • AutoBoolCounter should probably be not copyable link, + there are some extra brackets in the same file.
  • minor rounding issue link i.e. the integer division will never return non-integer megabytes.
  • suspicious casts link don't know specific reasoning for this one 😄

Plugin Support

CC : @probonopd

As you insisted on qt plugins instead of a library , I gave plugin support for this code which resides here in a different repo since some may want to use this as a library too(For those who dislike qt plugins).

Now the cool part about plugins is that you don't need to compile any source files of the updater as a developer and this reduces a lot of friction in the development ,however you atleast need a header file to describe the interface.

Another cool thing about plugins is that , plugins built using a major version can be used on all same major version of qt such that the minor version of the built must be less than or equal to the host minor version. Different major versions does not support at all. So we just need to pre-build a single version of plugin with Qt 5.0.0 to support all Qt 5.x.x and Qt 4.0.0 to support all Qt 4.x.x and so on.

So on prebuilt versions we need to distribute two files , a header file and a .so file which is the plugin itself and has to be placed inside the plugin dir relative to the application.

Here is a small video on the plugin -> https://www.youtube.com/watch?v=lhUsjbY0wEY&feature=youtu.be

You can get the prebuilt plugin from the releases.

Request for Ownership transfer

Hey @probonopd , I think this is a perfect time to transfer ownership to AppImage organization , What do you think ? Once you have the ownership , you can change the name or do anything with the project but don't worry since I will maintain it if you like. ❤️ 😄

Update error INVALID_ZSYNC_MTIME

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:
Trying to update my AppImage with the example application or the API results in the INVALID_ZSYNC_MTIME error. I'm creating the AppImage with linuxdeployqt.

Ways to Reproduce the issue (optional):

# build SimpleUpdate
cd AppImageUpdaterBridge/examples/SimpleUpdate
qmake && make

# grab updateable AppImage
wget https://releases.openclonk.org/snapshots/2019-02-03T18:14:53Z-master-918c4139e/OpenClonk-x86_64.AppImage

# update fails with SimpleUpdate:
./SimpleUpdate OpenClonk-x86_64.AppImage
# SimpleUpdate , A Simple Updater using AppImageUpdaterBridge.
# Copyright (C) 2018 , Antony Jr.
# [                          ###                              ]      Revising New Version at 0.0   error::  AppImageUpdaterBridge::errorCode(INVALID_ZSYNC_MTIME)

# update works with appimageupdatetool:
wget https://github.com/AppImage/AppImageUpdate/releases/download/continuous/appimageupdatetool-x86_64.AppImage
chmod +x appimageupdatetool-x86_64.AppImage
./appimageupdatetool-x86_64.AppImage OpenClonk-x86_64.AppImage
# Checking for updates...
# ... done!
# Starting update...
# [...]
# Update successful. New file created: OpenClonk-x86_64.AppImage

Discussion

What will this library do ?

  • Implement a simple to use interface to AppImageUpdater with Qt5 signals and slots
  • Create a easier to use C++ API.
  • Document the new High Level API , so everyone can use it
  • Create an Async model.

The goal is to make the library Qt friendly ( I'm bad at naming! ).

Any Thoughts?

Getting exception qappimageupdate.hpp: No such file or directory

Hello,

I was trying to integrate the QAppImageUpdate library as git submodules to one of the exting cmake project.

Followed the instructions as mentioned in the link: https://antonyjr.in/QAppImageUpdate/docs/Installation.html

Some it gives exception regarding header not found.
I will try to provide all the details that was done.

Here is the project structure:

- MyApp
  -- lib
    -- QAppImageUpdate
    -- CMakeLists.txt
  -- src
    ...
    -- CMakeLists.txt
    ...
  CMakeLists.txt

Added the library to existing project as submodules:

$ git submodule init
$ git submodule add https://github.com/antony-jr/QAppImageUpdate lib/QAppImageUpdate
$ git submodule update

In the top level CMakeLists.txt, have added the below snippet:

add_subdirectory(lib)

Added new lib -> CMakeLists.txt file:

# Add include directory
include_directories(QAppImageUpdate)

# include subdirectories 
add_subdirectory(QAppImageUpdate)

In the src -> CMakeLists.txt, have added the below snippet:

target_link_libraries(${PROJECT_NAME} ... ... QAppImageUpdate)

Next in one of the cpp file tried to include the QAppImageUpdate:

#include <QAppImageUpdate>

The cmake runs with no error but the make command gives the below exception.

In file included from /home/probal/code-workspace/nx-software-center-workspace/nx-software-center/src/models/appsmodel.cpp:13:
/home/probal/code-workspace/nx-software-center-workspace/nx-software-center/lib/QAppImageUpdate/QAppImageUpdate:35:10: fatal error: qappimageupdate.hpp: No such file or directory
   35 | #include "qappimageupdate.hpp"
      |          ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.

Can you please mention what is wrong here?
If there is anything that have been missed or not mentioned in the installation document?

Thanks.

#includes use brackets

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:

All the internal header files use #include <somefile.hpp> to include local files. This is problematic because it requires adding both /path/to/AppImageUpdaterBridge and /path/to/AppImageUpdaterBridge/include to the include path for users of the library. By using quotes instead (like #include "somefile.hpp"), the preprocessor will look for local files per default.

What to do with this library ?

As discussed in #1 , AppImageUpdaterBridge is now in pure C++ with a very good Qt API. I even re-implemented Zsync(As discussed) in C++ for it work more efficiently(And it does work good). To the best of my knowledge the code base is clean using only Qt API's and ensures portability.

These are the things I did

  • Re-implemented Zsync in C++ inheriting only the hash table.

zsync2 has a C++11 interface, so, standard types instead of the Qt versions (but actually it's all compatible...). I don't see the issue leading to the decision of @antony-jr to rewrite the original zsync (which has had a lot of issues, which took many weeks of intensive work to fix all those issues in zsync2. You shouldn't underestimate the amount of engineering that was necessary to create both libzsync2 and libappimageupdate. -- TheAssassin

  • Re-implemented the whole library in single threaded non-blocking API using Qt's event loop , Following a Worker-Object model.(Strictly , even for Zsync stuff)

  • Fully replaced libcurl's network support with Qt's Network Support , Now this library is generally faster when it comes to network since QNetworkAccessManager can do concurrent http request (maximum 6 at a time).

QNetworkAccessManager queues the requests it receives. The number of requests executed in parallel is dependent on the protocol. Currently, for the HTTP protocol on desktop platforms, 6 requests are executed in parallel for one host/port combination.

  • Added a AppImageUpdaterDialog class(not documented yet) which inherits QDialog and has the delta updater intrinsic to it , thus , once init() is called , Idle timer is started , The user can set the idle seconds , The default idle seconds is 0 seconds which will make the timer timeout when the event loop is free (i.e When the application is not doing anything). But the user can also override the event virtual method from QWidget or QMainWindow to reset the idle timer whenever an event is triggered to find the best time to show the self updater.(i.e show the updater when there is no mouse or keyboard events to their application)

  • Intelligent guessing of self update , i.e If you construct a AppImageDeltaRevisioner (Thats the main updater class) without any AppImage path , It will automatically guess the current AppImage path that is running the updater and so does not expect the user to provide any path , If you want to do a self update , Simply construct the updater class and start it off , Same goes for AppImageUpdaterDialog.

  • Completely thread safe, Tested with hardcore threading tests , But there is still no good way to test threads.(Thanks to Qt Signals and Slots.)

  • If HTTP Partial content is not supported by the server then automatically falls back to full download without doing the delta update , In this state , The updater simply becomes a traditional http downloader.

  • Does not do segmentation violation in any case to the best of my knowledge.

  • Cancel , Start and other control methods works smoothly.

  • Explicit logging if the developer wants , Disabling the logging can reduce overhead and binary size.

  • Does not touch the host system , like AppImageUpdate does(i.e AppImageUpdate sometimes deletes user files without any content integrity checks but this library does not touch the host machine at all , if the target file name exists it will rename the new target file with the current date time in ISO 8601 format placed in the middle of the filename , Thus avoiding deleting any files in the host machine.)

Try the new AppImageUpdater to test these out in action.

Here are some screenshots from AppImageUpdater ( You can get an idea on how fluid it is. )

Step 1: Start AppImageUpdater's latest version. ( It should auto update if any new releases are found).

1

Step 2: Run it.

2

3

4

5

Step 3: Drag and drop AppImage(s) to start update.

6

7

8

9

Step 4: Directly open your new version of AppImage , AppImageUpdater can be minimized to tray.

10

Step 5: Use your new version.

11

Now the question is , What do we plan to do with this library ? I really need some pointers on what I need to work on or just drop the library in favor of the official library.

CC: @probonopd , @TheAssassin

Crash if no appimage path set

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:
If the check at https://github.com/antony-jr/AppImageUpdaterBridge/blob/20842724c749488cc5966160133c76498b5ba77b/src/AppImageUpdateInformation_p.cc#L485 is skipped (because Qt does not have any arguments), the code crashes at https://github.com/antony-jr/AppImageUpdaterBridge/blob/20842724c749488cc5966160133c76498b5ba77b/src/AppImageUpdateInformation_p.cc#L516

Consider using QCommandLineParser

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:
Minor code style comment:
Consider using QCommandLineParser instead of manual argc, **argv manipulation.

Fails with InvalidMagicBytes when AppImageLauncher is installed

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:
I've been trying to use this library in my project to enable checking for AppImage updates and installing them from within the app. It works well in general but recently I found out that checking for updates functionality breaks when AppImageLauncher is installed.

AppImageLauncher is a project aiming to provide better integration of AppImages into the Linux desktop. I don't know in details how it works but it seems like it registers an interpreter for AppImage file type and hence gets the ability to intercept their launches. For example, when you try to launch some AppImage downloaded from the Internet, AppImageLauncher asks you whether you want to integrate this AppImage into the system (i.e. move it to ~/Applications) or just run it. Another thing that AppImageLauncher seems to be doing is changing the actual path to the AppImage from the application's POV: when AppImageDeltaRevisioner object is constructed without arguments, the path to AppImage it guesses automatically is not the actual path to the AppImage file but something like this instead:

/run/user/1000/appimagelauncherfs/0001.AppImage

I don't quite know what this executable is but it doesn't seem to be an actual AppImage. At least it doesn't contain A and I bytes which AppImageUpdaterBridge expects to be in place. For the actuall AppImage of my app I do see these bytes in place:

$ head -n 1 Quentier-x86_64_ef0106efad9cea0824a19d60aef4af2e.AppImage 
ELFAI>�F@@(�@@ @@@@@ <...>

For this executable I don't:

$ head -n 1 /run/user/1000/appimagelauncherfs/0001.AppImage
ELF>�F@@(�@@ @@@@@ <...>

So it's no surprise that check for magic bytes fails.

It's not immediately clear how AppImageUpdaterBridge can be adapted to AppImageLauncher presence. Perhaps some research is required first to figure out what exactly AppImageLauncher does to the actual AppImages when they are launched. Then AppImageUpdaterBridge could be able to detect that AppImageLauncher is installed (for example, looking at whether AppImageLauncher executable is within PATH) and act accordingly i.e. find some other way to figure out AppImage's type.

Ways to Reproduce the issue (optional):
Install AppImageLauncher, take any executable using this library and try to check for updates.

Mirror support

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:
Hello, is there a good way to provide mirrors? In our case we have two servers that provide the same AppImages, so it feels like a waste to only use one of them for the actual updates.

I am thinking that it would be cool to be able to use them simultaneously, as their bandwidth is obviously limited.
Selecting a mirror bases on ping and hops (like with netselect) might be interesting as well.

For most AppImages this doesn't seem too important, but in our case the AppImage is 1.3GiB so download speed matters quite a bit more.

Potential dereference of null pointer

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:
Potential dereference of nullptr.
Please see clang report in my gitlab-ci (link may expire)
That's why I don't like macros, because it makes things hard to read

Ways to Reproduce the issue (optional):

True GPG support without using GPL licensed libraries

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:

Since a long time ago AppImageUpdate has used sub-process to use gpg2 or gpg programs to verify the GPG signature by writing the signature files and other required files to a temporary directory and passing on the command line. Now I did not implement this because I hate using sub-process but it is my last resort. So I propose that we re-implement the signature verification code for GPG in pure C++ and have support for event loops too so that both Qt and the official version can benefit. This has to be a header only library so that anyone can use it without any hassle.

Consider avoiding macros

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:
Hi,
These are another codestyle suggestions:

THREAD_SAFE_AREA macro is really ugly, why not to use QMutexLocker? Do we really need always tryLock? Anyway RAII can do the job in both cases.

CONSTRUCT() macros is also very strange, why don't you use just a function?

Ways to Reproduce the issue (optional):
Look into the sources :-)

Windows stay open even if I say "No"

Select your issue type: (check at least one)

  • Bug
  • Question
  • Suggestion
  • Other (please describe):

Describe your issue:

These windows stay open even if I say "No" when I am asked whether I want to update

doesnotclose
needed

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.