From fe92700a1dae59a6b3ca6e6b68e0a833e811ae5b Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Wed, 24 Apr 2019 22:43:13 -0700 Subject: [PATCH] make a simple imager app Signed-off-by: Jeff Carr --- .gitignore | 1 + make-sdcard/Makefile | 3 + pinebook-imager/.gitignore | 1 + pinebook-imager/Makefile | 19 ++++ pinebook-imager/config.go | 88 ++++++++++++++++++ pinebook-imager/config.yml | 14 +++ pinebook-imager/main.go | 180 +++++++++++++++++++++++++++++++++++++ 7 files changed, 306 insertions(+) create mode 100644 pinebook-imager/.gitignore create mode 100644 pinebook-imager/Makefile create mode 100644 pinebook-imager/config.go create mode 100644 pinebook-imager/config.yml create mode 100644 pinebook-imager/main.go diff --git a/.gitignore b/.gitignore index 844ca56..606fd6a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ make-sdcard/make-sdcard random-output/random-output get-image/get-image connect-to-wifi/connect-to-wifi +pinebook-imager/pinebook-imager diff --git a/make-sdcard/Makefile b/make-sdcard/Makefile index 96c30fc..0cbf13a 100644 --- a/make-sdcard/Makefile +++ b/make-sdcard/Makefile @@ -3,6 +3,9 @@ all: # go get -u github.com/maxcnunes/gaper gaper +build-verbose: + go build -x -work + # simple sortcut to push all git changes push: git pull diff --git a/pinebook-imager/.gitignore b/pinebook-imager/.gitignore new file mode 100644 index 0000000..2ba2ca5 --- /dev/null +++ b/pinebook-imager/.gitignore @@ -0,0 +1 @@ +make-sdcard diff --git a/pinebook-imager/Makefile b/pinebook-imager/Makefile new file mode 100644 index 0000000..0cbf13a --- /dev/null +++ b/pinebook-imager/Makefile @@ -0,0 +1,19 @@ +all: + # 'gaper' is a simple and smart golang tool that just rebuilds every time you change a file + # go get -u github.com/maxcnunes/gaper + gaper + +build-verbose: + go build -x -work + +# simple sortcut to push all git changes +push: + git pull + git add --all + -git commit -a -s + git push + +# should update every go dependancy (?) +update: + git pull + go get -v -t -u ./... diff --git a/pinebook-imager/config.go b/pinebook-imager/config.go new file mode 100644 index 0000000..d409ccf --- /dev/null +++ b/pinebook-imager/config.go @@ -0,0 +1,88 @@ +package main + +/* + This simply parses the command line arguments using the default golang + package called 'flag'. This can be used as a simple template to parse + command line arguments in other programs. + + It puts everything in the 'config' package which I think is a good + wrapper around the 'flags' package and doesn't need a whole mess of + global variables +*/ + +import "log" +import "os" +import "flag" +import "fmt" +import "github.com/gookit/config" +import "github.com/gookit/config/yaml" + +var customUsage = func() { + fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0]) + flag.PrintDefaults() + + fmt.Println("") + fmt.Println("EXAMPLES:") + fmt.Println("") + fmt.Println(os.Args[0] + "--hostname test.hostname.wit.com") + fmt.Println("") +} + +func parseFlags() { + var version string + var race bool + var hostname string + var width int + var height int + + flag.StringVar (&version, "version", "v0.1", "Set compiled in version string") + + flag.StringVar (&hostname, "hostname", "localhost", "Your full hostname") + flag.IntVar (&width, "width", 400, "Width of the Window") + flag.IntVar (&height, "height", 600, "Height of the Window") + + flag.BoolVar (&race, "race", race, "Use race detector") + + // Set the output if something fails to stdout rather than stderr + flag.CommandLine.SetOutput(os.Stdout) + + flag.Usage = customUsage + flag.Parse() + + if flag.Parsed() { + log.Println("flag.Parse() worked") + } else { + log.Println("flag.Parse() failed") + } + + config.Set("width", width) + config.Set("height", height) + config.Set("hostname", hostname) +} + +func parseConfig() { + config.WithOptions(config.ParseEnv) + parseFlags() + + config.LoadOSEnv([]string{"MAIL"}) + config.LoadOSEnv([]string{"USER"}) + config.LoadOSEnv([]string{"BUILDDEBUG"}) + +/* + urls := flag.Args() + log.Println("flag.Aargs() = ", urls) + + for _, addr := range flag.Args() { + log.Println("GET %s", addr) + } +*/ + + // add driver for support yaml content + config.AddDriver(yaml.Driver) + config.LoadFiles("config.yml") + + for _, addr := range config.Strings("arr1") { + log.Println("addr =", addr) + } + +} diff --git a/pinebook-imager/config.yml b/pinebook-imager/config.yml new file mode 100644 index 0000000..2b05e48 --- /dev/null +++ b/pinebook-imager/config.yml @@ -0,0 +1,14 @@ +name: app2 +debug: false +baseKey: value2 +shell: ${SHELL} +envKey1: ${NotExist|defValue} + +map1: + key: val2 + key2: val20 + +arr1: + - lo + - wifi0 + - docker0 diff --git a/pinebook-imager/main.go b/pinebook-imager/main.go new file mode 100644 index 0000000..ce243b8 --- /dev/null +++ b/pinebook-imager/main.go @@ -0,0 +1,180 @@ +package main + +import "log" +import "reflect" +import "os" + +import "github.com/gookit/config" +import "github.com/andlabs/ui" +import "github.com/davecgh/go-spew/spew" + +import "git.wit.com/jcarr/shell" + +var mainwin *ui.Window +var mydrive string + +func rsync(mybut *ui.Button) { + log.Println("rsync() mybut =", reflect.ValueOf(mybut).Elem()) + + if _, err := os.Stat("/mnt/sdcard/lost+found/"); !os.IsNotExist(err) { + log.Println("run rsync here") + shell.Script(` + rsync -av --progress --inplace /home/pinebook/factory/FACTORY-IMAGER-ROOTFS/ /mnt/sdcard/ + umount /mnt/sdcard + `) + ui.MsgBox(mainwin, "The sdcard is finished", "") + } else { + log.Println("partition is not mounted") + ui.MsgBoxError(mainwin, "The partition is not mounted at /mnt/sdcard", "") + } +} + +func dd(mybut *ui.Button) { + if _, err := os.Stat("/mnt/factory-image/lost+found/"); os.IsNotExist(err) { + shell.Run("mkdir /mnt/factory-image/") + shell.Run("mount /dev/sdb2 /mnt/factory-image/") + } + if _, err := os.Stat("/mnt/factory-image/lost+found/"); os.IsNotExist(err) { + log.Println("partition is not mounted") + ui.MsgBoxError(mainwin, "The partition is not mounted at /mnt/sdcard", "") + return + } + + shell.Script("dd if=/home/pinebook/factory/factory-2019-01-20 of=/mnt/factory-image/factory-2019-01-20 status=progress oflag=sync"); + + ui.MsgBox(mainwin, "The sdcard is finished", "") +} + +// select the dev entry to partition and format +// for example: /dev/mtdblock0 or /dev/sdc +func selectDrive(mybox *ui.Combobox) { + spew.Dump(mybox.Visible()) + spew.Dump(mybox.Selected()) + spew.Dump(mybox.ControlBase) + // spew.Dump(box.ControlBase.Parent) + spew.Dump(mybox) + log.Println("selected = ", mybox.Selected()) + if (mybox.Selected() == 1) { + mydrive = "/dev/sdb" + } +} + +func format(mybut *ui.Button) { + log.Println("format() mybut =", reflect.ValueOf(mybut).Elem()) + log.Println("format and mount here") + + shell.Script(` + parted -s /dev/sdb mklabel msdos + parted -s /dev/sdb mkpart primary ext4 1MiB 8GB + parted -s /dev/sdb mkpart primary ext4 8GB 32GB + sleep 1 + mkfs.ext4 /dev/sdb1 + mkfs.ext4 /dev/sdb2 + e2label /dev/sdb1 root + e2label /dev/sdb2 factory-image + mount /dev/sdb1 /mnt/sdcard/ + pwd + dd if=../u-boot/u-boot-sunxi-with-spl.bin of=/dev/sdb status=progress oflag=sync bs=1K seek=8 + `) +} + +func addButton(vbox *ui.Box, label string, click func(*ui.Button)) { + hbox := ui.NewHorizontalBox() + hbox.SetPadded(true) + + // look up translation here for 'label' + button := ui.NewButton(label) + hbox.Append(button, false) + button.OnClicked(click) + + vbox.Append(hbox, false) +} + +func addGroupBox(hbox *ui.Box, name string) *ui.Box { + groupDrive := ui.NewGroup(name) + groupDrive.SetMargined(true) + + vbox := ui.NewVerticalBox() + vbox.SetPadded(true) + + groupDrive.SetChild(vbox) + hbox.Append(groupDrive, true) + + log.Println("groupDrive =", reflect.TypeOf(groupDrive)) + + vbox.SetPadded(true) + return vbox +} + +func makeBurnSDcardPage() *ui.Box { + hbox := ui.NewVerticalBox() + hbox.SetPadded(true) + + vbox := addGroupBox(hbox, "Select Distribution") + + cbox := ui.NewCombobox() + cbox.Append("Armbian") + cbox.Append("Debian") + cbox.Append("Manjaro") + cbox.Append("q4os") + cbox.Append("android") + cbox.OnSelected(selectDrive) + vbox.Append(cbox, false) + + vbox2 := addGroupBox(hbox, "Select the Image") + + addButton(vbox2, "Download", format) + addButton(vbox2, "Burn file to eMMC", dd) + addButton(vbox2, "md5sum", rsync) + + return hbox +} + +func makeHardwarePage() *ui.Box { + hbox := ui.NewVerticalBox() + hbox.SetPadded(true) + + vbox := addGroupBox(hbox, "Hardware Info") + + addButton(vbox, "something", format) + + return hbox +} + +func setupUI() { + mainwin = ui.NewWindow("Pinebook eMMC Imager", config.Int("width"), config.Int("height"), false) + + mainwin.OnClosing(func(*ui.Window) bool { + ui.Quit() + return true + }) + + ui.OnShouldQuit(func() bool { + mainwin.Destroy() + return true + }) + + tab := ui.NewTab() + mainwin.SetChild(tab) + mainwin.SetMargined(true) + + tab.Append("Burn eMMC", makeBurnSDcardPage()) + tab.SetMargined(0, true) + +/* + tab2 := ui.NewTab() + mainwin.SetChild(tab2) + mainwin.SetMargined(true) + + tab2.Append("Hardware", makeHardwarePage()) + tab2.SetMargined(1, true) +*/ + + mainwin.Show() +} + +func main() { + parseConfig() + + ui.Main(setupUI) +}