Commit c73e9a7f authored by Roman Alifanov's avatar Roman Alifanov

implemented update process

parent ad1b9069
......@@ -98,6 +98,16 @@ type Package struct {
TypePackage int `json:"typePackage"`
}
type EventData struct {
Name string `json:"name"`
View string `json:"message"`
State string `json:"state"`
Type string `json:"type"`
ProgressPercent float64 `json:"progress"`
ProgressDone string `json:"progressDone"`
Transaction string `json:"transaction,omitempty"`
}
type InfoResponse struct {
Message string `json:"message"`
PackageInfo Package `json:"packageInfo"`
......
......@@ -3,12 +3,20 @@ package apm
import (
"SystemUpdater/lib/apm/sudbus"
"encoding/json"
"fmt"
"log"
"sync"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/godbus/dbus/v5"
)
type UpdaterSource interface {
GetPackageChanges() PackageChanges
RunUpgrade(
func(),
func(EventData),
) error
}
type PackageChanges struct {
......@@ -70,6 +78,86 @@ type SystemUpdatesSource struct {
obj dbus.BusObject
}
func (s *SystemUpdatesSource) RunUpgrade(
onDone func(),
onLog func(EventData),
) error {
conn, err := dbus.SystemBus()
if err != nil {
return fmt.Errorf("connect system bus: %w", err)
}
err = conn.AddMatchSignal(
dbus.WithMatchSender("org.altlinux.APM"),
dbus.WithMatchObjectPath("/org/altlinux/APM"),
)
if err != nil {
return fmt.Errorf("add match signal: %w", err)
}
obj := conn.Object("org.altlinux.APM", "/org/altlinux/APM")
stopSignals := make(chan struct{})
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
sigCh := make(chan *dbus.Signal, 10)
conn.Signal(sigCh)
for {
select {
case sig := <-sigCh:
if sig == nil {
return
}
fmt.Printf("RAW SIGNAL: %+v\n", sig)
if len(sig.Body) > 0 {
raw, ok := sig.Body[0].(string)
if ok {
var data EventData
if err := json.Unmarshal([]byte(raw), &data); err == nil {
glib.IdleAdd(func() { onLog(data) })
} else {
fmt.Println("JSON decode error:", err)
}
}
}
case <-stopSignals:
return
}
}
}()
go func() {
defer wg.Done()
call := obj.Call(
"org.altlinux.APM.system.Upgrade",
0,
"Ximper System Updater",
)
if call.Err != nil {
log.Println("DBus call error:", call.Err)
} else if len(call.Body) > 0 {
log.Println("DBus reply:", call.Body[0])
}
close(stopSignals)
glib.IdleAdd(onDone)
}()
wg.Wait()
return nil
}
func (s *SystemUpdatesSource) GetPackageChanges() PackageChanges {
reply := s.obj.Call("org.altlinux.APM.system.CheckUpgrade", 0, "Ximper System Updater")
return updatesOutputProcessing(reply)
......
......@@ -11,8 +11,8 @@ import (
_ "embed"
"github.com/diamondburned/gotk4-adwaita/pkg/adw"
"github.com/diamondburned/gotk4/pkg/core/glib"
"github.com/diamondburned/gotk4/pkg/gio/v2"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
)
......@@ -64,6 +64,7 @@ func (su *SystemUpdater) onActivate() {
window.FillWithChanges(su, updates)
window.stack.SetVisibleChildName("main")
window.updateButton.ConnectActivated(window.StartUpdateProcess)
return false
}
......@@ -76,9 +77,10 @@ var SystemUpdaterWindowUIXML string
type SystemUpdaterWindow struct {
*adw.ApplicationWindow
navView *adw.NavigationView
listbox *gtk.ListBox
stack *gtk.Stack
navView *adw.NavigationView
listbox *gtk.ListBox
stack *gtk.Stack
updateButton *adw.ButtonRow
}
var mainWin *SystemUpdaterWindow
......@@ -92,12 +94,14 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow {
navView := bldr.GetObject[*adw.NavigationView](builder, "navigationv")
listbox := bldr.GetObject[*gtk.ListBox](builder, "updates_listbox")
stack := bldr.GetObject[*gtk.Stack](builder, "main_stack")
updateButton := bldr.GetObject[*adw.ButtonRow](builder, "apply_button")
mainWin = &SystemUpdaterWindow{
win,
navView,
listbox,
stack,
updateButton,
}
}
return mainWin
......@@ -105,10 +109,14 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow {
func (sw *SystemUpdaterWindow) FillWithChanges(su *SystemUpdater, u []apm.PackageChanges) {
for _, updatesList := range u {
sw.listbox.Append(NewUpdateRow("System packages", updatesList))
sw.listbox.Append(NewUpdateRow("System packages", updatesList, sw.StartUpdateProcess))
}
}
func (sw *SystemUpdaterWindow) StartUpdateProcess() {
RunUpgrade(apm.NewUpdatesSources())
}
func SystemUpdaterApplication(su *SystemUpdater) {
su.App.ConnectActivate(func() {
su.onActivate()
......@@ -164,5 +172,6 @@ func SystemUpdaterApplication(su *SystemUpdater) {
}
func main() {
glib.LogSetDebugEnabled(false)
SystemUpdaterApplication(GetSystemUpdater())
}
......@@ -44,24 +44,26 @@ type SystemUpdaterListPage struct {
applyButton *adw.ButtonRow
}
func NewListPage() *SystemUpdaterListPage {
func NewListPage(runUpgrade func()) *SystemUpdaterListPage {
builder := bldr.New(SystemUpdaterListPageUIXML)
page := bldr.GetObject[*adw.NavigationPage](builder, "listpage")
listbox := bldr.GetObject[*gtk.ListBox](builder, "updates_listbox")
applyButton := bldr.GetObject[*adw.ButtonRow](builder, "apply_button")
applyButton.ConnectActivated(runUpgrade)
return &SystemUpdaterListPage{page, listbox, applyButton}
}
func NewUpdateRow(name string, info apm.PackageChanges) *adw.ActionRow {
func NewUpdateRow(name string, info apm.PackageChanges, runUpgradeCallback func()) *adw.ActionRow {
win := GetSystemUpdaterWindow()
urow := adw.NewActionRow()
urow.SetTitle(name)
urow.SetActivatable(true)
upage := NewListPage()
upage := NewListPage(runUpgradeCallback)
urow.ConnectActivated(func() {
win.navView.Push(upage.nav)
......@@ -106,7 +108,7 @@ func NewUpdateRow(name string, info apm.PackageChanges) *adw.ActionRow {
row.SetTitle(title)
row.SetActivatable(true)
page := NewListPage()
page := NewListPage(runUpgradeCallback)
row.ConnectActivated(func() {
win.navView.Push(page.nav)
......
......@@ -26,6 +26,9 @@
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkProgressBar" id="progress_bar"/>
</child>
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<child>
......
......@@ -58,14 +58,15 @@
(5,7,"AdwStatusPage","status_page",6,None,None,None,0,None,None),
(5,8,"AdwClamp",None,7,None,None,None,0,None,None),
(5,9,"GtkBox",None,8,None,None,None,0,None,None),
(5,10,"GtkListBox",None,9,None,None,None,0,None,None),
(5,10,"GtkListBox",None,9,None,None,None,1,None,None),
(5,11,"AdwExpanderRow",None,10,None,None,None,0,None,None),
(5,12,"GtkScrolledWindow",None,11,None,None,None,0,None,None),
(5,13,"GtkTextView","log_view",12,None,None,None,0,None,None),
(5,15,"GtkStackPage",None,5,None,None,None,1,None,None),
(5,16,"AdwStatusPage",None,15,None,None,None,0,None,None),
(5,17,"GtkButton","restart_button",16,None,None,None,0,None,None),
(5,18,"AdwNavigationPage","process_page",None,None,None,None,0,None,None)
(5,18,"AdwNavigationPage","process_page",None,None,None,None,0,None,None),
(5,19,"GtkProgressBar","progress_bar",9,None,None,None,0,None,None)
</object>
<object_property>
(1,1,"GtkWidget","height-request","294",0,None,None,None,None,None,None,None,None),
......
package main
import (
"SystemUpdater/lib/apm"
bldr "SystemUpdater/lib/gtks/builder"
_ "embed"
"github.com/diamondburned/gotk4-adwaita/pkg/adw"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
)
//go:embed process-page.ui
var ProcessPageUIXML string
type SystemUpdaterProcessPage struct {
}
func appendLog(logView *gtk.TextView, text string) {
buf := logView.Buffer()
iter := buf.EndIter()
buf.Insert(iter, text)
}
func RunUpgrade(srcs apm.UpdatesSources) {
builder := bldr.New(ProcessPageUIXML)
page := bldr.GetObject[*adw.NavigationPage](builder, "process_page")
GetSystemUpdaterWindow().navView.Replace([]*adw.NavigationPage{
page,
})
stack := bldr.GetObject[*gtk.Stack](builder, "process_stack")
statusPage := bldr.GetObject[*adw.StatusPage](builder, "status_page")
progressBar := bldr.GetObject[*gtk.ProgressBar](builder, "progress_bar")
logView := bldr.GetObject[*gtk.TextView](builder, "log_view")
go func() {
IA := glib.IdleAdd
for name, u := range srcs {
glib.IdleAdd(func() { appendLog(logView, "=== Starting update "+name+" ===\n") })
err := u.RunUpgrade(
func() {
IA(func() { appendLog(logView, "=== Update has been completed ===\n") })
},
func(ev apm.EventData) {
IA(func() {
appendLog(logView, ev.View+"\n")
statusPage.SetDescription(ev.View)
if ev.ProgressPercent > 0 {
progressBar.SetFraction(float64(ev.ProgressPercent) / 100)
}
})
},
)
if err != nil {
IA(func() { appendLog(logView, "Error during the update "+name+": "+err.Error()+"\n") })
break
}
IA(func() { progressBar.SetFraction(0) })
}
IA(func() { stack.SetVisibleChildName("finish") })
_ = stack
}()
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment