depot-linux 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +10 -0
- data/README.md +56 -0
- data/Rakefile +10 -0
- data/bin/depot +8 -0
- data/bin/depot-gui +14 -0
- data/bin/setup-rubyqt6 +72 -0
- data/fixtures/assets/download.png +0 -0
- data/fixtures/flatpakrefs/org.qbittorrent.qBittorrent.flatpakref +10 -0
- data/fixtures/rpms/Modrinth App-0.13.14-1.x86_64.rpm +0 -0
- data/lib/depot/app_customizer.rb +152 -0
- data/lib/depot/assets.rb +11 -0
- data/lib/depot/backends/app_image.rb +210 -0
- data/lib/depot/backends/archive.rb +263 -0
- data/lib/depot/backends/deb.rb +265 -0
- data/lib/depot/backends/flatpak_ref.rb +123 -0
- data/lib/depot/backends/rpm.rb +280 -0
- data/lib/depot/backends/support.rb +39 -0
- data/lib/depot/cli.rb +344 -0
- data/lib/depot/desktop_entry.rb +37 -0
- data/lib/depot/doctor.rb +59 -0
- data/lib/depot/gui/app.rb +23 -0
- data/lib/depot/gui/drop_panel.rb +80 -0
- data/lib/depot/gui/main_window.rb +1196 -0
- data/lib/depot/inspection.rb +52 -0
- data/lib/depot/inspector.rb +387 -0
- data/lib/depot/installer.rb +54 -0
- data/lib/depot/manifest_store.rb +53 -0
- data/lib/depot/packages/archive.rb +188 -0
- data/lib/depot/packages/deb.rb +262 -0
- data/lib/depot/packages/flatpak_ref.rb +90 -0
- data/lib/depot/packages/rpm.rb +301 -0
- data/lib/depot/paths.rb +57 -0
- data/lib/depot/result.rb +13 -0
- data/lib/depot/sandbox.rb +285 -0
- data/lib/depot/settings.rb +43 -0
- data/lib/depot/source_resolver.rb +36 -0
- data/lib/depot/uninstaller.rb +90 -0
- data/lib/depot/update_downloader.rb +136 -0
- data/lib/depot/updater.rb +230 -0
- data/lib/depot/util.rb +33 -0
- data/lib/depot/version.rb +5 -0
- data/lib/depot.rb +21 -0
- metadata +139 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "util"
|
|
4
|
+
|
|
5
|
+
module Depot
|
|
6
|
+
class DesktopEntry
|
|
7
|
+
attr_reader :app_id, :name, :exec_path, :icon_name
|
|
8
|
+
|
|
9
|
+
def initialize(app_id:, name:, exec_path:, icon_name: nil)
|
|
10
|
+
@app_id = app_id
|
|
11
|
+
@name = name
|
|
12
|
+
@exec_path = exec_path
|
|
13
|
+
@icon_name = icon_name
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def contents
|
|
17
|
+
lines = [
|
|
18
|
+
"[Desktop Entry]",
|
|
19
|
+
"Type=Application",
|
|
20
|
+
"Version=1.0",
|
|
21
|
+
"Name=#{escape(name)}",
|
|
22
|
+
"Exec=#{Util.desktop_exec_quote(exec_path)}",
|
|
23
|
+
"Terminal=false",
|
|
24
|
+
"Categories=Utility;",
|
|
25
|
+
"X-Depot-AppID=#{escape(app_id)}"
|
|
26
|
+
]
|
|
27
|
+
lines << "Icon=#{escape(icon_name)}" if icon_name && !icon_name.empty?
|
|
28
|
+
lines.join("\n") + "\n"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def escape(value)
|
|
34
|
+
value.to_s.gsub("\\", "\\\\\\").gsub("\n", "\\n")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/depot/doctor.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "manifest_store"
|
|
4
|
+
require_relative "paths"
|
|
5
|
+
require_relative "source_resolver"
|
|
6
|
+
|
|
7
|
+
module Depot
|
|
8
|
+
class Doctor
|
|
9
|
+
TOOLS = %w[flatpak bwrap bsdtar gtk-update-icon-cache update-desktop-database].freeze
|
|
10
|
+
|
|
11
|
+
def initialize(store: ManifestStore.new)
|
|
12
|
+
@store = store
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def report
|
|
16
|
+
{
|
|
17
|
+
"tools" => TOOLS.to_h { |tool| [tool, command_available?(tool)] },
|
|
18
|
+
"paths" => {
|
|
19
|
+
"data_dir" => Dir.exist?(Paths.data_dir),
|
|
20
|
+
"apps_dir" => Dir.exist?(Paths.apps_dir),
|
|
21
|
+
"manifests_dir" => Dir.exist?(Paths.manifests_dir),
|
|
22
|
+
"desktop_entries_dir" => Dir.exist?(Paths.desktop_entries_dir)
|
|
23
|
+
},
|
|
24
|
+
"manifests" => manifest_checks
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def healthy?
|
|
29
|
+
report.fetch("manifests").all? { |manifest| manifest.fetch("ok") }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def manifest_checks
|
|
35
|
+
@store.all.map do |manifest|
|
|
36
|
+
issues = []
|
|
37
|
+
issues << "missing installed executable" if missing_path?(manifest["installed_executable"])
|
|
38
|
+
issues << "missing desktop entry" if manifest["desktop_entry"].to_s != "" && !File.exist?(manifest["desktop_entry"])
|
|
39
|
+
source = manifest["install_source"]
|
|
40
|
+
issues << "missing original source" if source.to_s != "" && SourceResolver.resolve(source).nil?
|
|
41
|
+
{
|
|
42
|
+
"app_id" => manifest["app_id"],
|
|
43
|
+
"name" => manifest["display_name"],
|
|
44
|
+
"backend" => manifest["backend"],
|
|
45
|
+
"ok" => issues.empty?,
|
|
46
|
+
"issues" => issues
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def missing_path?(path)
|
|
52
|
+
path.to_s == "" || !File.exist?(path)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def command_available?(command)
|
|
56
|
+
ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).any? { |dir| File.executable?(File.join(dir, command)) }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "qt6/qtwidgets"
|
|
4
|
+
require_relative "../../depot"
|
|
5
|
+
require_relative "drop_panel"
|
|
6
|
+
require_relative "main_window"
|
|
7
|
+
|
|
8
|
+
module Depot
|
|
9
|
+
module GUI
|
|
10
|
+
module App
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
def run
|
|
14
|
+
app = QApplication.new
|
|
15
|
+
QApplication.set_application_name("Depot")
|
|
16
|
+
QApplication.set_organization_name("Depot")
|
|
17
|
+
QApplication.set_window_icon(QIcon.new(Assets.logo_path)) if File.exist?(Assets.logo_path)
|
|
18
|
+
MainWindow.new.show
|
|
19
|
+
app.exec
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Depot
|
|
4
|
+
module GUI
|
|
5
|
+
class DropPanel < RubyQt6::Bando::QFrame
|
|
6
|
+
def initialize(&on_file)
|
|
7
|
+
super()
|
|
8
|
+
@on_file = on_file
|
|
9
|
+
set_accept_drops(true)
|
|
10
|
+
set_object_name("depotDropPanel")
|
|
11
|
+
set_frame_shape(QFrame::StyledPanel)
|
|
12
|
+
set_minimum_height(280)
|
|
13
|
+
|
|
14
|
+
@label = QLabel.new("Drop software here")
|
|
15
|
+
@label.set_alignment(Qt::AlignCenter)
|
|
16
|
+
@label.set_word_wrap(true)
|
|
17
|
+
@label.set_object_name("depotDropTitle")
|
|
18
|
+
@label.set_attribute(Qt::WA_TransparentForMouseEvents)
|
|
19
|
+
@hint = QLabel.new("or choose a package with the file picker")
|
|
20
|
+
@hint.set_alignment(Qt::AlignCenter)
|
|
21
|
+
@hint.set_object_name("depotDropHint")
|
|
22
|
+
@hint.set_attribute(Qt::WA_TransparentForMouseEvents)
|
|
23
|
+
|
|
24
|
+
layout = QVBoxLayout.new
|
|
25
|
+
layout.add_stretch
|
|
26
|
+
layout.add_widget(@label)
|
|
27
|
+
layout.add_widget(@hint)
|
|
28
|
+
layout.add_stretch
|
|
29
|
+
set_layout(layout)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def drag_enter_event(event)
|
|
33
|
+
if file_from_event(event)
|
|
34
|
+
@hint.set_text("Release to inspect this software")
|
|
35
|
+
event.accept_proposed_action
|
|
36
|
+
else
|
|
37
|
+
event.ignore
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def drag_leave_event(event)
|
|
42
|
+
@hint.set_text("or choose a package with the file picker")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def drag_move_event(event)
|
|
46
|
+
if file_from_event(event)
|
|
47
|
+
event.accept_proposed_action
|
|
48
|
+
else
|
|
49
|
+
event.ignore
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def drop_event(event)
|
|
54
|
+
path = file_from_event(event)
|
|
55
|
+
return event.ignore unless path
|
|
56
|
+
|
|
57
|
+
@hint.set_text("or choose a package with the file picker")
|
|
58
|
+
@on_file.call(path)
|
|
59
|
+
event.accept_proposed_action
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def file_from_event(event)
|
|
65
|
+
mime = event.mime_data
|
|
66
|
+
return nil unless mime.respond_to?(:has_urls) && mime.has_urls
|
|
67
|
+
|
|
68
|
+
url = mime.urls.first
|
|
69
|
+
return nil unless url
|
|
70
|
+
|
|
71
|
+
local = url.to_local_file.to_s
|
|
72
|
+
return nil if local.empty?
|
|
73
|
+
|
|
74
|
+
local
|
|
75
|
+
rescue StandardError
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|