Commit c73e9a7f authored by Roman Alifanov's avatar Roman Alifanov

implemented update process

parent ad1b9069
...@@ -98,6 +98,16 @@ type Package struct { ...@@ -98,6 +98,16 @@ type Package struct {
TypePackage int `json:"typePackage"` 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 { type InfoResponse struct {
Message string `json:"message"` Message string `json:"message"`
PackageInfo Package `json:"packageInfo"` PackageInfo Package `json:"packageInfo"`
......
...@@ -3,12 +3,20 @@ package apm ...@@ -3,12 +3,20 @@ package apm
import ( import (
"SystemUpdater/lib/apm/sudbus" "SystemUpdater/lib/apm/sudbus"
"encoding/json" "encoding/json"
"fmt"
"log"
"sync"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
) )
type UpdaterSource interface { type UpdaterSource interface {
GetPackageChanges() PackageChanges GetPackageChanges() PackageChanges
RunUpgrade(
func(),
func(EventData),
) error
} }
type PackageChanges struct { type PackageChanges struct {
...@@ -70,6 +78,86 @@ type SystemUpdatesSource struct { ...@@ -70,6 +78,86 @@ type SystemUpdatesSource struct {
obj dbus.BusObject 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 { func (s *SystemUpdatesSource) GetPackageChanges() PackageChanges {
reply := s.obj.Call("org.altlinux.APM.system.CheckUpgrade", 0, "Ximper System Updater") reply := s.obj.Call("org.altlinux.APM.system.CheckUpgrade", 0, "Ximper System Updater")
return updatesOutputProcessing(reply) return updatesOutputProcessing(reply)
......
...@@ -11,8 +11,8 @@ import ( ...@@ -11,8 +11,8 @@ import (
_ "embed" _ "embed"
"github.com/diamondburned/gotk4-adwaita/pkg/adw" "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/gio/v2"
"github.com/diamondburned/gotk4/pkg/glib/v2"
"github.com/diamondburned/gotk4/pkg/gtk/v4" "github.com/diamondburned/gotk4/pkg/gtk/v4"
) )
...@@ -64,6 +64,7 @@ func (su *SystemUpdater) onActivate() { ...@@ -64,6 +64,7 @@ func (su *SystemUpdater) onActivate() {
window.FillWithChanges(su, updates) window.FillWithChanges(su, updates)
window.stack.SetVisibleChildName("main") window.stack.SetVisibleChildName("main")
window.updateButton.ConnectActivated(window.StartUpdateProcess)
return false return false
} }
...@@ -79,6 +80,7 @@ type SystemUpdaterWindow struct { ...@@ -79,6 +80,7 @@ type SystemUpdaterWindow struct {
navView *adw.NavigationView navView *adw.NavigationView
listbox *gtk.ListBox listbox *gtk.ListBox
stack *gtk.Stack stack *gtk.Stack
updateButton *adw.ButtonRow
} }
var mainWin *SystemUpdaterWindow var mainWin *SystemUpdaterWindow
...@@ -92,12 +94,14 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow { ...@@ -92,12 +94,14 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow {
navView := bldr.GetObject[*adw.NavigationView](builder, "navigationv") navView := bldr.GetObject[*adw.NavigationView](builder, "navigationv")
listbox := bldr.GetObject[*gtk.ListBox](builder, "updates_listbox") listbox := bldr.GetObject[*gtk.ListBox](builder, "updates_listbox")
stack := bldr.GetObject[*gtk.Stack](builder, "main_stack") stack := bldr.GetObject[*gtk.Stack](builder, "main_stack")
updateButton := bldr.GetObject[*adw.ButtonRow](builder, "apply_button")
mainWin = &SystemUpdaterWindow{ mainWin = &SystemUpdaterWindow{
win, win,
navView, navView,
listbox, listbox,
stack, stack,
updateButton,
} }
} }
return mainWin return mainWin
...@@ -105,10 +109,14 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow { ...@@ -105,10 +109,14 @@ func GetSystemUpdaterWindow() *SystemUpdaterWindow {
func (sw *SystemUpdaterWindow) FillWithChanges(su *SystemUpdater, u []apm.PackageChanges) { func (sw *SystemUpdaterWindow) FillWithChanges(su *SystemUpdater, u []apm.PackageChanges) {
for _, updatesList := range u { 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) { func SystemUpdaterApplication(su *SystemUpdater) {
su.App.ConnectActivate(func() { su.App.ConnectActivate(func() {
su.onActivate() su.onActivate()
...@@ -164,5 +172,6 @@ func SystemUpdaterApplication(su *SystemUpdater) { ...@@ -164,5 +172,6 @@ func SystemUpdaterApplication(su *SystemUpdater) {
} }
func main() { func main() {
glib.LogSetDebugEnabled(false)
SystemUpdaterApplication(GetSystemUpdater()) SystemUpdaterApplication(GetSystemUpdater())
} }
...@@ -44,24 +44,26 @@ type SystemUpdaterListPage struct { ...@@ -44,24 +44,26 @@ type SystemUpdaterListPage struct {
applyButton *adw.ButtonRow applyButton *adw.ButtonRow
} }
func NewListPage() *SystemUpdaterListPage { func NewListPage(runUpgrade func()) *SystemUpdaterListPage {
builder := bldr.New(SystemUpdaterListPageUIXML) builder := bldr.New(SystemUpdaterListPageUIXML)
page := bldr.GetObject[*adw.NavigationPage](builder, "listpage") page := bldr.GetObject[*adw.NavigationPage](builder, "listpage")
listbox := bldr.GetObject[*gtk.ListBox](builder, "updates_listbox") listbox := bldr.GetObject[*gtk.ListBox](builder, "updates_listbox")
applyButton := bldr.GetObject[*adw.ButtonRow](builder, "apply_button") applyButton := bldr.GetObject[*adw.ButtonRow](builder, "apply_button")
applyButton.ConnectActivated(runUpgrade)
return &SystemUpdaterListPage{page, listbox, applyButton} 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() win := GetSystemUpdaterWindow()
urow := adw.NewActionRow() urow := adw.NewActionRow()
urow.SetTitle(name) urow.SetTitle(name)
urow.SetActivatable(true) urow.SetActivatable(true)
upage := NewListPage() upage := NewListPage(runUpgradeCallback)
urow.ConnectActivated(func() { urow.ConnectActivated(func() {
win.navView.Push(upage.nav) win.navView.Push(upage.nav)
...@@ -106,7 +108,7 @@ func NewUpdateRow(name string, info apm.PackageChanges) *adw.ActionRow { ...@@ -106,7 +108,7 @@ func NewUpdateRow(name string, info apm.PackageChanges) *adw.ActionRow {
row.SetTitle(title) row.SetTitle(title)
row.SetActivatable(true) row.SetActivatable(true)
page := NewListPage() page := NewListPage(runUpgradeCallback)
row.ConnectActivated(func() { row.ConnectActivated(func() {
win.navView.Push(page.nav) win.navView.Push(page.nav)
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="spacing">12</property> <property name="spacing">12</property>
<child> <child>
<object class="GtkProgressBar" id="progress_bar"/>
</child>
<child>
<object class="GtkListBox"> <object class="GtkListBox">
<property name="selection-mode">none</property> <property name="selection-mode">none</property>
<child> <child>
......
...@@ -58,14 +58,15 @@ ...@@ -58,14 +58,15 @@
(5,7,"AdwStatusPage","status_page",6,None,None,None,0,None,None), (5,7,"AdwStatusPage","status_page",6,None,None,None,0,None,None),
(5,8,"AdwClamp",None,7,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,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,11,"AdwExpanderRow",None,10,None,None,None,0,None,None),
(5,12,"GtkScrolledWindow",None,11,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,13,"GtkTextView","log_view",12,None,None,None,0,None,None),
(5,15,"GtkStackPage",None,5,None,None,None,1,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,16,"AdwStatusPage",None,15,None,None,None,0,None,None),
(5,17,"GtkButton","restart_button",16,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>
<object_property> <object_property>
(1,1,"GtkWidget","height-request","294",0,None,None,None,None,None,None,None,None), (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