Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ff48fae713 | |||
| 645f2d8dd9 | |||
| 90f47a3456 | |||
| 096b5052a8 | |||
| e3ca19c1d1 | |||
| e4e5adaf13 | |||
| 7a2ebd533e | |||
| 2f0ca5418c | |||
| ce9d4aed23 | |||
| 712a5ab33d | |||
| 6723f933b4 | |||
| 016fc35745 | |||
| ba5e3510ec | |||
| 7e2d7ee14b | |||
| b20de4f1d6 | |||
| d2e91baa6b | |||
| a0f22e480b | |||
| 57f921c2cb | |||
| 55f897db46 | |||
| 3d9583281e | |||
| ec4d66f6b2 | |||
| c442ef5688 | |||
| 78d3723bf4 | |||
| 828b9f4cda | |||
| be64aa083f | |||
| 3111705cae | |||
| 868ae8f700 | |||
| 226e9d6210 | |||
| 56748f043e | |||
| 3d3239fe0a | |||
| 6e643b68ac | |||
| 539f33d25e | |||
| 4d3cb9f486 | |||
| a55c82483a | |||
| 9e9bb82025 | |||
| ea91d3cd80 | |||
| 2a0d53db09 | |||
| a0213d1886 | |||
| 695ce815d9 | |||
| 01556c1eb0 | |||
| d7410bb88f | |||
| bc63e6d10f | |||
| 0403825c3d | |||
| 0f1bb3fabd | |||
| 78c6842fab | |||
| dc1edbad3a | |||
| 6dd00c5f8f | |||
| e68337886f | |||
| 3b639f53fd | |||
| 3199ad88fd | |||
| a221d18d33 | |||
| a9eeb3bb1c | |||
| 844a282fd7 | |||
| 9da352a315 | |||
| 34b8f7c926 | |||
| 5d5cedec58 | |||
| 8441a8b752 | |||
| d64d88e0a5 | |||
| 5eeb9cc702 | |||
| fc3411e568 |
@@ -0,0 +1 @@
|
|||||||
|
/testing
|
||||||
@@ -1,32 +1,51 @@
|
|||||||
# LinuxPA
|
# LinuxPA
|
||||||
|
|
||||||
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
|
LinuxPA is a try to bring a [PortableApps.com](http://portableapps.com) type launcher to Linux.
|
||||||
|
|
||||||
# How to use
|
## How to use
|
||||||
Just double click on an app to launch it! If there are multiple executables, you can either select the specific executable, or if you just double click the app it'll launch the first linux executable, but if one isn't found it launches the first executable in general.
|
|
||||||
|
Just double click on an app to launch it! If there are multiple executables, you can either select the specific executable, or if you just double click the app it'll launch the first linux executable it finds. .sh script files have priority over other executable files.
|
||||||
|
|
||||||
|
## Apps
|
||||||
|
|
||||||
|
The below place provides linux executables that don't need libs installed on the host system:
|
||||||
|
[https://appimage.github.io/](https://appimage.github.io/)
|
||||||
|
|
||||||
|
## PortableApps.com Compatibility
|
||||||
|
|
||||||
# PortableApps.com Compatibility
|
|
||||||
LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format.
|
LinuxPA works will with the PortableApps.com launcher, as it looks for apps in the PortableApps folder and grabs the app's name and icon from where it should be in the PortableApps.com format.
|
||||||
|
My forum at PortableApps.com can be found [here](http://portableapps.com/node/54998).
|
||||||
|
|
||||||
# common.sh
|
## common.sh
|
||||||
common.sh is found in the PortableApps/LinuxPACom folder and is executed before the app. I mainly use it to set environment variables (such as HOME).
|
|
||||||
|
|
||||||
# Simple App Setup
|
common.sh is found in the PortableApps/LinuxPACom folder and is executed before the app. I mainly use it to set environment variables (such as HOME). You can create and edit the common.sh from settings.
|
||||||
Because apps aren't natively formated in the PortableApps.com format, if LinuxPA doesn't find the AppInfo.ini or appicon_\*.png in the App/AppInfo folder of the app it looks for them in the root directory of the app (except it looks, nor for appicon_\*.png, but appicon.png). If an AppInfo.ini file isn't found then the name of the app is grabbed from the folder name and it's category is set to other. It specifically looks for the lines starting with `Name=` and `Category=`
|
|
||||||
|
|
||||||
# AppImage Support
|
## Simple App Setup
|
||||||
[AppImage Website](http://appimage.org)
|
|
||||||
Right now AppImages are simply supported via the native linux executable support, but later I'm hoping to add downloading and automatic updating support later on.
|
|
||||||
|
|
||||||
# USB mount
|
Because apps aren't natively formated in the PortableApps.com format, LinuxPA will look in the root directory for a AppInfo.ini (for basic info such as category and name) and appicon.png. If they aren't found, it looks where the appicon_\*.png and AppInfo.ini is in PortableApps format. You can set what the AppInfo.ini and appicon.png are from LinuxPA.
|
||||||
Unfortunately Linux, by default, doesn't support running executables off of flash drives, requiring you to mount your drive with special mount arguments, I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
|
|
||||||
|
|
||||||
# Screenshots
|
## AppImage Support
|
||||||
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6)
|
|
||||||
|
|
||||||
# TODO (Might be in order)
|
[AppImage Website](http://appimage.org)
|
||||||
1. MAKE IT BETTER
|
I'm looking into improving AppImage support. As of 2.1.5.0 IF `unsquashfs` is in $PATH then some advanced AppImage support is available and it will automagically get the name and possibly the icon of it. I'm looking into better support, but it might be a while.
|
||||||
1. Add settings menu
|
|
||||||
1. Add updater for .AppImage files
|
## USB mount
|
||||||
1. Download .AppImage files (maybe)
|
|
||||||
1. Check if all apps are closed when it closes and ask if you want to force stop the apps.
|
Unfortunately Linux, by default, doesn't support running executables off of FAT formated flash drives, requiring you to mount your drive with special mount arguments or format in a linux friendly format (such as EXT4). I personally use the arguments `exec,noauto,nodev,nosuid,umask=0000`
|
||||||
1. Portable wine???
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
Photos are found [Here](https://goo.gl/photos/VtBUL6DyZTMidj5n6). The screenshots are with the adapta gtk theme
|
||||||
|
|
||||||
|
## TODO (Might be in order)
|
||||||
|
|
||||||
|
1. MAKE IT BETTER
|
||||||
|
1. Integrate [goappimage](https://github.com/probonod/go-appimage) library for better AppImage integration.
|
||||||
|
1. Try to `chmod +x` executables if they don't have the permission
|
||||||
|
1. Manual update check
|
||||||
|
1. Better AppImage integrations (Specifically updating and better appimage downloading)
|
||||||
|
1. Get information (such as name and icon) directly from an appimage
|
||||||
|
1. Better appimage downloading (probably based around [AppImageHub](https://appimage.github.io/apps/))
|
||||||
|
1. Sandboxing support
|
||||||
|
1. Might be possible by packaging as an AppImage and providing Firejail, or simply just downloading it (like with Wine)
|
||||||
|
1. Check if all apps are closed when it closes and ask if you want to force stop the apps
|
||||||
|
|||||||
@@ -1,259 +1,113 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"path/filepath"
|
||||||
"sort"
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
"github.com/probonopd/go-appimage/src/goappimage"
|
||||||
"github.com/nelsam/gxui/math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type app struct {
|
type ExeType byte
|
||||||
name string
|
|
||||||
cat string
|
const (
|
||||||
appimg []string
|
Script = ExeType(iota + 1)
|
||||||
lin []string
|
AppImage
|
||||||
ex []string
|
ELF
|
||||||
icon gxui.Texture
|
Win
|
||||||
dir string
|
)
|
||||||
ini *os.File
|
|
||||||
|
type Exe struct {
|
||||||
|
Filename string
|
||||||
|
Type ExeType
|
||||||
}
|
}
|
||||||
|
|
||||||
type appExNode struct {
|
type App struct {
|
||||||
ap app
|
Name string
|
||||||
exInd int
|
Execs []Exe
|
||||||
|
// Image []byte TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appExNode) launch() {
|
func ProcessAppImage(fil string) (*App, error) {
|
||||||
if wine {
|
ai, err := goappimage.NewAppImage(fil)
|
||||||
var cmd *exec.Cmd
|
if err != nil {
|
||||||
if ind := sort.SearchStrings(a.ap.lin, a.ap.ex[a.exInd]); ind == len(a.ap.lin) {
|
return nil, err
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[a.exInd]+"\"")
|
}
|
||||||
|
app := App{
|
||||||
|
Name: ai.Name,
|
||||||
|
// Image: ,
|
||||||
|
Execs: []Exe{
|
||||||
|
{
|
||||||
|
Filename: fil,
|
||||||
|
Type: AppImage,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &app, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProcessDir(dir string) (*App, error) {
|
||||||
|
fils, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to list files in %v: %v\n", dir, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
app := App{
|
||||||
|
Name: filepath.Base(dir),
|
||||||
|
}
|
||||||
|
for _, f := range fils {
|
||||||
|
if f.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var t ExeType
|
||||||
|
if strings.HasSuffix(strings.ToLower(f.Name()), ".exe") {
|
||||||
|
t = Win
|
||||||
} else {
|
} else {
|
||||||
if comEnbld {
|
fil, err := os.Open(filepath.Join(dir, f.Name()))
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
if err != nil {
|
||||||
} else {
|
log.Printf("Error opening %v: %v\n", filepath.Join(dir, f.Name()), err)
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
continue
|
||||||
|
}
|
||||||
|
startByts := make([]byte, 4)
|
||||||
|
_, err = fil.Read(startByts)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error reading starting bytes of %v: %v\n", filepath.Join(dir, f.Name()), err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if bytes.HasPrefix(startByts, []byte("#!")) {
|
||||||
|
t = Script
|
||||||
|
} else if bytes.Contains(bytes.ToLower(startByts), []byte("elf")) {
|
||||||
|
if strings.HasSuffix(strings.ToLower(f.Name()), ".so") || strings.Contains(strings.ToLower(f.Name()), ".so.") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if goappimage.IsAppImage(filepath.Join(dir, f.Name())) {
|
||||||
|
t = AppImage
|
||||||
|
} else {
|
||||||
|
t = ELF
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
if t != 0 {
|
||||||
cmd.Stderr = os.Stderr
|
app.Execs = append(app.Execs, Exe{
|
||||||
cmd.Start()
|
Filename: f.Name(),
|
||||||
|
Type: t,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var cmd *exec.Cmd
|
if len(app.Execs) == 0 {
|
||||||
if comEnbld {
|
return nil, nil
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[a.exInd]+"\"")
|
|
||||||
}
|
}
|
||||||
cmd.Stdout = os.Stdout
|
slices.SortFunc(app.Execs, func(a, b Exe) int {
|
||||||
cmd.Stderr = os.Stderr
|
if a.Type > b.Type {
|
||||||
cmd.Start()
|
return 1
|
||||||
}
|
} else if a.Type < b.Type {
|
||||||
|
return -1
|
||||||
func (a *appExNode) Count() int {
|
}
|
||||||
return 0
|
return strings.Compare(a.Filename, b.Filename)
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) NodeAt(int) gxui.TreeNode {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) ItemIndex(gxui.AdapterItem) int {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) Item() gxui.AdapterItem {
|
|
||||||
if wine {
|
|
||||||
return a.ap.ex[a.exInd]
|
|
||||||
}
|
|
||||||
return a.ap.lin[a.exInd]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appExNode) Create(the gxui.Theme) gxui.Control {
|
|
||||||
box := the.CreateLinearLayout()
|
|
||||||
box.SetDirection(gxui.LeftToRight)
|
|
||||||
box.SetVerticalAlignment(gxui.AlignMiddle)
|
|
||||||
img := the.CreateImage()
|
|
||||||
img.SetTexture(a.ap.icon)
|
|
||||||
img.SetExplicitSize(math.Size{H: 32, W: 32})
|
|
||||||
lbl := the.CreateLabel()
|
|
||||||
lbl.SetText(a.ap.ex[a.exInd])
|
|
||||||
box.AddChild(img)
|
|
||||||
box.AddChild(lbl)
|
|
||||||
box.OnDoubleClick(func(gxui.MouseEvent) {
|
|
||||||
a.launch()
|
|
||||||
})
|
})
|
||||||
return box
|
//TODO: get "proper" name & icon, either from AppImage or PortableApps spec
|
||||||
}
|
return &app, nil
|
||||||
|
|
||||||
type appNode struct {
|
|
||||||
ap app
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appNode) launch() {
|
|
||||||
|
|
||||||
if len(a.ap.ex) == 1 {
|
|
||||||
if wine {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if ind := sort.SearchStrings(a.ap.lin, a.ap.ex[0]); ind == len(a.ap.lin) {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
} else {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.ex[0]+"\"")
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if wine {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if len(a.ap.lin) == 0 {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; wine \""+a.ap.ex[0]+"\"")
|
|
||||||
} else {
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[0]+"\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
} else {
|
|
||||||
if len(a.ap.lin) != 0 {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
if comEnbld {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", ". PortableApps/LinuxPACom/common.sh || exit 1;cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[0]+"\"")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("/bin/sh", "-c", "cd \""+a.ap.dir+"\"; \"./"+a.ap.lin[0]+"\"")
|
|
||||||
}
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appNode) Count() int {
|
|
||||||
if wine {
|
|
||||||
if len(a.ap.ex) > 1 {
|
|
||||||
return len(a.ap.ex)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(a.ap.lin) > 1 {
|
|
||||||
return len(a.ap.lin)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appNode) NodeAt(i int) gxui.TreeNode {
|
|
||||||
return &appExNode{ap: a.ap, exInd: i}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appNode) ItemIndex(item gxui.AdapterItem) int {
|
|
||||||
if wine {
|
|
||||||
for i, v := range a.ap.ex {
|
|
||||||
if v == item {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i, v := range a.ap.lin {
|
|
||||||
if v == item {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appNode) Item() gxui.AdapterItem {
|
|
||||||
return a.ap.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *appNode) Create(the gxui.Theme) gxui.Control {
|
|
||||||
box := the.CreateLinearLayout()
|
|
||||||
box.SetDirection(gxui.LeftToRight)
|
|
||||||
box.SetPadding(math.CreateSpacing(2))
|
|
||||||
box.SetVerticalAlignment(gxui.AlignMiddle)
|
|
||||||
img := the.CreateImage()
|
|
||||||
if a.ap.icon != nil {
|
|
||||||
img.SetTexture(a.ap.icon)
|
|
||||||
}
|
|
||||||
img.SetExplicitSize(math.Size{H: 32, W: 32})
|
|
||||||
lbl := the.CreateLabel()
|
|
||||||
lbl.SetText(a.ap.name)
|
|
||||||
box.AddChild(img)
|
|
||||||
box.AddChild(lbl)
|
|
||||||
box.OnDoubleClick(func(gxui.MouseEvent) {
|
|
||||||
a.launch()
|
|
||||||
})
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
|
|
||||||
type catAdap struct {
|
|
||||||
gxui.AdapterBase
|
|
||||||
cat string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) setCat(cat string) {
|
|
||||||
a.cat = cat
|
|
||||||
a.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) refresh() {
|
|
||||||
a.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) Count() int {
|
|
||||||
if wine {
|
|
||||||
return len(master[a.cat])
|
|
||||||
}
|
|
||||||
return len(linmaster[a.cat])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) NodeAt(i int) gxui.TreeNode {
|
|
||||||
if wine {
|
|
||||||
return &appNode{ap: master[a.cat][i]}
|
|
||||||
}
|
|
||||||
return &appNode{ap: linmaster[a.cat][i]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) Size(gxui.Theme) math.Size {
|
|
||||||
return math.Size{H: 34, W: math.MaxSize.W}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *catAdap) ItemIndex(item gxui.AdapterItem) int {
|
|
||||||
if wine {
|
|
||||||
for i, v := range master[a.cat] {
|
|
||||||
if v.name == item {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i, v := range linmaster[a.cat] {
|
|
||||||
if v.name == item {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
module github.com/CalebQ42/LinuxPA
|
||||||
|
|
||||||
|
go 1.23.1
|
||||||
|
|
||||||
|
require github.com/probonopd/go-appimage v0.0.0-20240922191415-5cf876da9cdc
|
||||||
|
|
||||||
|
require (
|
||||||
|
gioui.org v0.7.1 // indirect
|
||||||
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect
|
||||||
|
gioui.org/shader v1.0.8 // indirect
|
||||||
|
github.com/CalebQ42/squashfs v1.0.2 // indirect
|
||||||
|
github.com/adrg/xdg v0.5.0 // indirect
|
||||||
|
github.com/alokmenghrajani/gpgeez v0.0.0-20161206084504-1a06f1c582f9 // indirect
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.5.0 // indirect
|
||||||
|
github.com/emirpasic/gods v1.12.0 // indirect
|
||||||
|
github.com/go-text/typesetting v0.1.1 // indirect
|
||||||
|
github.com/google/go-github v17.0.0+incompatible // indirect
|
||||||
|
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 // indirect
|
||||||
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
|
||||||
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||||
|
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e // indirect
|
||||||
|
github.com/sergi/go-diff v1.0.0 // indirect
|
||||||
|
github.com/src-d/gcfg v1.4.0 // indirect
|
||||||
|
github.com/therootcompany/xz v1.0.1 // indirect
|
||||||
|
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||||
|
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
||||||
|
golang.org/x/crypto v0.27.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect
|
||||||
|
golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37 // indirect
|
||||||
|
golang.org/x/image v0.18.0 // indirect
|
||||||
|
golang.org/x/net v0.27.0 // indirect
|
||||||
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
golang.org/x/text v0.18.0 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
|
||||||
|
gopkg.in/src-d/go-git.v4 v4.13.1 // indirect
|
||||||
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
gioui.org v0.7.1 h1:l7OVj47n1z8acaszQ6Wlu+Rxme+HqF3q8b+Fs68+x3w=
|
||||||
|
gioui.org v0.7.1/go.mod h1:5Kw/q7R1BWc5MKStuTNvhCgSrRqbfHc9Dzfjs4IGgZo=
|
||||||
|
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
||||||
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
|
||||||
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
||||||
|
gioui.org/shader v1.0.8 h1:6ks0o/A+b0ne7RzEqRZK5f4Gboz2CfG+mVliciy6+qA=
|
||||||
|
gioui.org/shader v1.0.8/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
|
||||||
|
github.com/CalebQ42/squashfs v1.0.2 h1:r1OMSTpacV4GXOWaLwnydEpcrv+yhUSIzrvSGYO74Xg=
|
||||||
|
github.com/CalebQ42/squashfs v1.0.2/go.mod h1:uhKIQfq2+dgJ+utqCkvVk0t7XuqaNhcotCrqSI0wUuI=
|
||||||
|
github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
|
||||||
|
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
|
||||||
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||||
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||||
|
github.com/alokmenghrajani/gpgeez v0.0.0-20161206084504-1a06f1c582f9 h1:Zio/mdDEpJDG1yeH9y2Kcb9ATWXkE7WIBkO+IMqRbbM=
|
||||||
|
github.com/alokmenghrajani/gpgeez v0.0.0-20161206084504-1a06f1c582f9/go.mod h1:u65XFfs2+s//7QVkp5Q1NEZl4zVep2BtubxiSXJERN8=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||||
|
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk=
|
||||||
|
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||||
|
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||||
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
|
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||||
|
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
|
github.com/go-text/typesetting v0.1.1 h1:bGAesCuo85nXnEN5LmFMVGAGpGkCPtHrZLi//qD7EJo=
|
||||||
|
github.com/go-text/typesetting v0.1.1/go.mod h1:d22AnmeKq/on0HNv73UFriMKc4Ez6EqZAofLhAzpSzI=
|
||||||
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||||
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
|
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0=
|
||||||
|
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||||
|
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||||
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/probonopd/go-appimage v0.0.0-20240922191415-5cf876da9cdc h1:m+G8q9mghEL9nU4sbdHBP0uFWe7/0k3IqeRIn5TrPnU=
|
||||||
|
github.com/probonopd/go-appimage v0.0.0-20240922191415-5cf876da9cdc/go.mod h1:WIMiirlWSahyTIR4hOMWhMojo2Xxqtk/bi/YSNyWYDg=
|
||||||
|
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e h1:dCWirM5F3wMY+cmRda/B1BiPsFtmzXqV9b0hLWtVBMs=
|
||||||
|
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e/go.mod h1:9leZcVcItj6m9/CfHY5Em/iBrCz7js8LcRQGTKEEv2M=
|
||||||
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||||
|
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
|
||||||
|
github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
|
||||||
|
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||||
|
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
|
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||||
|
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||||
|
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||||
|
golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w=
|
||||||
|
golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
|
golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37 h1:SOSg7+sueresE4IbmmGM60GmlIys+zNX63d6/J4CMtU=
|
||||||
|
golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37/go.mod h1:3F+MieQB7dRYLTmnncoFbb1crS5lfQoTfDgQy6K4N0o=
|
||||||
|
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||||
|
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||||
|
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||||
|
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||||
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
|
||||||
|
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||||
|
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
|
||||||
|
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||||
|
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||||
|
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -1,31 +1,42 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nelsam/gxui"
|
"fmt"
|
||||||
"github.com/nelsam/gxui/drivers/gl"
|
"os"
|
||||||
"github.com/nelsam/gxui/themes/dark"
|
|
||||||
|
"gioui.org/app"
|
||||||
|
"gioui.org/op"
|
||||||
|
"gioui.org/widget/material"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
const (
|
||||||
dr gxui.Driver
|
version = "3.0.0-alpha1"
|
||||||
th gxui.Theme
|
|
||||||
master map[string][]app
|
|
||||||
linmaster map[string][]app
|
|
||||||
cats []string
|
|
||||||
lin []string
|
|
||||||
wine bool
|
|
||||||
comEnbld bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
master = make(map[string][]app)
|
go func() {
|
||||||
linmaster = make(map[string][]app)
|
w := &app.Window{}
|
||||||
gl.StartDriver(appMain)
|
w.Option(app.Size(500, 500), app.Title("LinuxPA"))
|
||||||
|
if err := ui(w); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
|
app.Main()
|
||||||
}
|
}
|
||||||
|
|
||||||
func appMain(dri gxui.Driver) {
|
func ui(w *app.Window) error {
|
||||||
dr = dri
|
th := material.NewTheme()
|
||||||
th = dark.CreateTheme(dr)
|
op := &op.Ops{}
|
||||||
setup()
|
for {
|
||||||
ui()
|
switch e := w.Event().(type) {
|
||||||
|
case app.DestroyEvent:
|
||||||
|
return e.Err
|
||||||
|
case app.FrameEvent:
|
||||||
|
ctx := app.NewContext(op, e)
|
||||||
|
lbl := material.Body1(th, "Hello there!")
|
||||||
|
lbl.Layout(ctx)
|
||||||
|
e.Frame(op)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testImage = "https://darkstorm.tech/files/LinuxPATest.sfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setupTestEnv() error {
|
||||||
|
_, err := exec.LookPath("unsquashfs")
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("unsquashfs not installed")
|
||||||
|
}
|
||||||
|
fold, err := os.Stat("testing")
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = os.Mkdir("testing", 0777)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fold, err = os.Stat("testing")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
os.RemoveAll("testing/PortableApps")
|
||||||
|
os.RemoveAll("testing/Documents")
|
||||||
|
os.RemoveAll("testing/Start.exe")
|
||||||
|
if !fold.IsDir() {
|
||||||
|
return errors.New("./testing is not a directory!!!")
|
||||||
|
}
|
||||||
|
img, err := os.Open("testing/LinuxPATest.sfs")
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
img, err = os.Create("testing/LinuxPATest.sfs")
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("Cannot create testing/LinuxPATest.sfs")
|
||||||
|
}
|
||||||
|
resp, err := http.DefaultClient.Get(testImage)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(img, resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = exec.Command("unsquashfs", "-d", "./testing", "./testing/LinuxPATest.sfs").Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStuff(t *testing.T) {
|
||||||
|
setupTestEnv()
|
||||||
|
main()
|
||||||
|
}
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
_ "image/png"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setup() {
|
|
||||||
PortableAppsFold, err := os.Open("PortableApps")
|
|
||||||
if PAStat, _ := PortableAppsFold.Stat(); err != nil || !PAStat.IsDir() {
|
|
||||||
panic("PortableApps folder not found!!")
|
|
||||||
}
|
|
||||||
PAFolds, _ := PortableAppsFold.Readdirnames(-1)
|
|
||||||
sort.Strings(PAFolds)
|
|
||||||
for _, v := range PAFolds {
|
|
||||||
fold, _ := os.Open("PortableApps/" + v)
|
|
||||||
if stat, _ := fold.Stat(); stat.IsDir() && stat.Name() != "PortableApps.com" && stat.Name() != "LinuxPACom" {
|
|
||||||
ap := processApp("PortableApps/" + v)
|
|
||||||
if !reflect.DeepEqual(ap, app{}) {
|
|
||||||
if _, ok := master[ap.cat]; !ok {
|
|
||||||
cats = append(cats, ap.cat)
|
|
||||||
sort.Strings(cats)
|
|
||||||
if len(ap.lin) != 0 {
|
|
||||||
lin = append(lin, ap.cat)
|
|
||||||
sort.Strings(lin)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if len(ap.lin) != 0 {
|
|
||||||
ind := sort.SearchStrings(lin, ap.cat)
|
|
||||||
if ind == len(lin) {
|
|
||||||
lin = append(lin, ap.cat)
|
|
||||||
sort.Strings(lin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(ap.lin) != 0 {
|
|
||||||
linmaster[ap.cat] = append(linmaster[ap.cat], ap)
|
|
||||||
}
|
|
||||||
master[ap.cat] = append(master[ap.cat], ap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func processApp(fold string) (out app) {
|
|
||||||
wd, _ := os.Getwd()
|
|
||||||
out.dir = wd + "/" + fold
|
|
||||||
out.ini = findInfo(fold)
|
|
||||||
if out.ini != nil {
|
|
||||||
out.name = getName(out.ini)
|
|
||||||
out.ini = findInfo(fold)
|
|
||||||
out.cat = getCat(out.ini)
|
|
||||||
out.ini = findInfo(fold)
|
|
||||||
}
|
|
||||||
if out.name == "" {
|
|
||||||
out.name = strings.TrimPrefix(fold, "PortableApps/")
|
|
||||||
}
|
|
||||||
if out.cat == "" {
|
|
||||||
out.cat = "Other"
|
|
||||||
}
|
|
||||||
out.icon = getIcon(fold)
|
|
||||||
folder, _ := os.Open(fold)
|
|
||||||
fis, _ := folder.Readdirnames(-1)
|
|
||||||
for _, v := range fis {
|
|
||||||
tmp, _ := os.Open(fold + "/" + v)
|
|
||||||
if stat, _ := tmp.Stat(); stat.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(strings.ToLower(v), ".appimage") {
|
|
||||||
out.appimg = append(out.appimg, v)
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
out.lin = append(out.lin, v)
|
|
||||||
} else if strings.HasSuffix(strings.ToLower(v), ".exe") {
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
} else {
|
|
||||||
btys := make([]byte, 4)
|
|
||||||
rdr := bufio.NewReader(tmp)
|
|
||||||
rdr.Read(btys)
|
|
||||||
if strings.HasPrefix(strings.ToLower(string(btys)), "ELF") || strings.HasPrefix(strings.ToLower(string(btys)), "#!") {
|
|
||||||
out.ex = append(out.ex, v)
|
|
||||||
out.lin = append(out.lin, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(out.ex) == 0 {
|
|
||||||
return app{}
|
|
||||||
}
|
|
||||||
if len(out.lin) == 0 {
|
|
||||||
out.name += " (Wine)"
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCat(ini *os.File) string {
|
|
||||||
rdr := bufio.NewReader(ini)
|
|
||||||
var ret string
|
|
||||||
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
|
||||||
if strings.HasPrefix(string(line), "Category=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "Category=")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rdr.Reset(ini)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func getName(ini *os.File) string {
|
|
||||||
rdr := bufio.NewReader(ini)
|
|
||||||
var ret string
|
|
||||||
for line, _, err := rdr.ReadLine(); err == nil; line, _, err = rdr.ReadLine() {
|
|
||||||
if strings.HasPrefix(string(line), "Name=") {
|
|
||||||
ret = strings.TrimPrefix(string(line), "Name=")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rdr.Reset(ini)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIcon(fold string) gxui.Texture {
|
|
||||||
var pic *os.File
|
|
||||||
if folder, err := os.Open(fold + "/App/AppInfo"); err == nil {
|
|
||||||
fis, _ := folder.Readdir(-1)
|
|
||||||
var pics []string
|
|
||||||
for _, v := range fis {
|
|
||||||
if !v.IsDir() && strings.HasSuffix(strings.ToLower(v.Name()), ".png") && strings.HasPrefix(strings.ToLower(v.Name()), "appicon_") {
|
|
||||||
pics = append(pics, v.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(pics)
|
|
||||||
if len(pics) > 1 {
|
|
||||||
ind := sort.SearchStrings(pics, "appicon_32.png")
|
|
||||||
if ind == len(pics) {
|
|
||||||
ind--
|
|
||||||
}
|
|
||||||
pic, _ = os.Open(fold + "/App/AppInfo/" + pics[ind])
|
|
||||||
}
|
|
||||||
} else if fi, err := os.Open(fold + "/appicon.png"); err == nil {
|
|
||||||
pic = fi
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
img, _, err := image.Decode(pic)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rgba := image.NewRGBA(img.Bounds())
|
|
||||||
draw.Draw(rgba, img.Bounds(), img, image.ZP, draw.Src)
|
|
||||||
ret := dr.CreateTexture(rgba, 1)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func findInfo(fold string) *os.File {
|
|
||||||
tmp, err := os.Open(fold + "/App/AppInfo")
|
|
||||||
if err == nil {
|
|
||||||
fis, _ := tmp.Readdirnames(-1)
|
|
||||||
for _, v := range fis {
|
|
||||||
if strings.ToLower(v) == "appinfo.ini" {
|
|
||||||
tmp, _ := os.Open(fold + "/App/AppInfo/" + v)
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if fi, err := os.Open(fold + "/appinfo.ini"); err == nil {
|
|
||||||
return fi
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
-65
@@ -1,65 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
"github.com/nelsam/gxui/math"
|
|
||||||
)
|
|
||||||
|
|
||||||
//StrList TODO
|
|
||||||
type StrList struct {
|
|
||||||
gxui.AdapterBase
|
|
||||||
strs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
//AddString TODO
|
|
||||||
func (s *StrList) AddString(add string) {
|
|
||||||
s.strs = append(s.strs, add)
|
|
||||||
s.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove TODO
|
|
||||||
func (s *StrList) Remove(index int) {
|
|
||||||
s.strs = append(s.strs[:index], s.strs[index+1:]...)
|
|
||||||
s.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//SetStrings TODO
|
|
||||||
func (s *StrList) SetStrings(strs []string) {
|
|
||||||
s.strs = strs
|
|
||||||
s.DataChanged(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//Count TODO
|
|
||||||
func (s *StrList) Count() int {
|
|
||||||
return len(s.strs)
|
|
||||||
}
|
|
||||||
|
|
||||||
//ItemAt TODO
|
|
||||||
func (s *StrList) ItemAt(index int) gxui.AdapterItem {
|
|
||||||
return s.strs[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
//ItemIndex TODO
|
|
||||||
func (s *StrList) ItemIndex(item gxui.AdapterItem) int {
|
|
||||||
for i, v := range s.strs {
|
|
||||||
if v == item {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create TODO
|
|
||||||
func (s *StrList) Create(th gxui.Theme, index int) gxui.Control {
|
|
||||||
box := th.CreateLinearLayout()
|
|
||||||
box.SetDirection(gxui.LeftToRight)
|
|
||||||
lbl := th.CreateLabel()
|
|
||||||
lbl.SetText(s.strs[index])
|
|
||||||
box.AddChild(lbl)
|
|
||||||
return box
|
|
||||||
}
|
|
||||||
|
|
||||||
//Size TODO
|
|
||||||
func (s *StrList) Size(gxui.Theme) math.Size {
|
|
||||||
return math.Size{W: math.MaxSize.W, H: 20}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/nelsam/gxui"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ui() {
|
|
||||||
catListAdap := &StrList{}
|
|
||||||
appListAdap := &catAdap{}
|
|
||||||
catListAdap.SetStrings(lin)
|
|
||||||
win := th.CreateWindow(500, 500, "LinuxPA")
|
|
||||||
top := th.CreateLinearLayout()
|
|
||||||
top.SetDirection(gxui.BottomToTop)
|
|
||||||
splBox := th.CreateLinearLayout()
|
|
||||||
spl := th.CreateSplitterLayout()
|
|
||||||
spl.SetOrientation(gxui.Horizontal)
|
|
||||||
catList := th.CreateList()
|
|
||||||
catList.SetAdapter(catListAdap)
|
|
||||||
catList.OnSelectionChanged(func(it gxui.AdapterItem) {
|
|
||||||
appListAdap.setCat(it.(string))
|
|
||||||
})
|
|
||||||
appList := th.CreateTree()
|
|
||||||
appList.SetAdapter(appListAdap)
|
|
||||||
spl.AddChild(catList)
|
|
||||||
spl.AddChild(appList)
|
|
||||||
splBox.AddChild(spl)
|
|
||||||
butBox := th.CreateLinearLayout()
|
|
||||||
butBox.SetDirection(gxui.LeftToRight)
|
|
||||||
if _, err := exec.LookPath("wine"); err == nil {
|
|
||||||
wineBut := th.CreateButton()
|
|
||||||
wineBut.SetType(gxui.ToggleButton)
|
|
||||||
wineBut.SetChecked(wine)
|
|
||||||
wineBut.SetText("Show Windows Apps")
|
|
||||||
wineBut.OnClick(func(gxui.MouseEvent) {
|
|
||||||
wine = wineBut.IsChecked()
|
|
||||||
appListAdap.refresh()
|
|
||||||
if wineBut.IsChecked() {
|
|
||||||
catListAdap.SetStrings(cats)
|
|
||||||
wineBut.SetText("Hide Windows Apps")
|
|
||||||
} else {
|
|
||||||
catListAdap.SetStrings(lin)
|
|
||||||
wineBut.SetText("Show Windows Apps")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
butBox.AddChild(wineBut)
|
|
||||||
}
|
|
||||||
top.AddChild(butBox)
|
|
||||||
top.AddChild(splBox)
|
|
||||||
win.AddChild(top)
|
|
||||||
win.OnClose(dr.Terminate)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user