Skip to content

Commit

Permalink
Code refactoring based on go fmt and golint tools
Browse files Browse the repository at this point in the history
  • Loading branch information
artemdevel committed Mar 10, 2016
1 parent 65f84c1 commit 2f23f45
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 235 deletions.
31 changes: 16 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,37 @@ import (
"os"
)

// BuildRev var is set from the command line and used in ShowBanner function.
var BuildRev string

const VMS_URL = "https://dev.windows.com/en-us/microsoft-edge/tools/vms/windows/"
const vmsURL = "https://dev.windows.com/en-us/microsoft-edge/tools/vms/windows/"

func main() {
utils.ShowBanner(BuildRev)
args := os.Args[1:]
if len(args) == 0 {
raw_data := utils.DownloadJson(VMS_URL)
platforms, hypervisors, browsers, available_vms := utils.ParseJson(&raw_data)
rawData := utils.DownloadJSON(vmsURL)
platforms, hypervisors, browsers, availableVms := utils.ParseJSON(&rawData)

user_choice := utils.UserChoice{}
user_choice.Platform = utils.SelectOption(
userChoice := utils.UserChoice{}
userChoice.Platform = utils.SelectOption(
platforms, "Select platform", "All", utils.GetDefaultPlatform)
user_choice.Hypervisor = utils.SelectOption(
hypervisors, "Select hypervisor", user_choice.Platform, utils.GetDefaultHypervisor)
user_choice.BrowserOs = utils.SelectOption(
browsers, "Select browser and OS", user_choice.Hypervisor, utils.GetDefaultBrowser)
user_choice.VmImage = available_vms[user_choice.Spec]
user_choice.DownloadPath = utils.SelectOption(
userChoice.Hypervisor = utils.SelectOption(
hypervisors, "Select hypervisor", userChoice.Platform, utils.GetDefaultHypervisor)
userChoice.BrowserOs = utils.SelectOption(
browsers, "Select browser and OS", userChoice.Hypervisor, utils.GetDefaultBrowser)
userChoice.VMImage = availableVms[userChoice.Spec]
userChoice.DownloadPath = utils.SelectOption(
utils.GetDownloadPaths(), "Select download path", "All", utils.GetDefaultDownloadPath)
utils.ConfirmUsersChoice(user_choice)
utils.ConfirmUsersChoice(userChoice)

utils.DownloadVm(user_choice)
utils.DownloadVM(userChoice)
utils.EnterToContinue("Download finished")

vm_path := utils.UnzipVm(user_choice)
vmPath := utils.UnzipVM(userChoice)
utils.EnterToContinue("Unzip finished")

utils.InstallVm(user_choice.Hypervisor, vm_path)
utils.InstallVM(userChoice.Hypervisor, vmPath)
} else {
// TODO: process command-line args
}
Expand Down
48 changes: 25 additions & 23 deletions utils/cli.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
// Very simple console interface
// Package utils contains various supplementary functions and data structures.
// This file cli.go contains functions for very simple console interface.
package utils

import (
"bufio"
"fmt"
"os"
"bufio"
"strings"
"runtime"
"strconv"
"sort"
"strconv"
"strings"
)

// Show application's greeting banner
// ShowBanner function shows application's greeting banner.
func ShowBanner(rev string) {
fmt.Printf("Get IE tool. Build rev %s.\n", rev)
}

// Yes/No choice
// YesNoConfirmation function shows Yes/No choice. N is default choice for now.
func YesNoConfirmation(msg string) {
reader := bufio.NewReader(os.Stdin)
defer fmt.Println()
Expand All @@ -31,7 +32,7 @@ func YesNoConfirmation(msg string) {
}
}

// Press ENTER to continue
// EnterToContinue function shows press ENTER confirmation for a give message.
func EnterToContinue(msg string) {
reader := bufio.NewReader(os.Stdin)
if runtime.GOOS == "darwin" {
Expand All @@ -42,38 +43,39 @@ func EnterToContinue(msg string) {
reader.ReadString('\n')
}

// Select an option from 'menu'
func SelectOption(choices ChoiceGroups, group_msg, group_name string, default_choice_func DefaultChoice) string {
// SelectOption function shows simple selection 'menu'.
func SelectOption(choices ChoiceGroups, groupMsg, groupName string, defaultChoiceFunc DefaultChoice) string {
reader := bufio.NewReader(os.Stdin)
defer fmt.Println()

sorted_choices := choices[group_name]
sort.Sort(sorted_choices)
default_choice := default_choice_func(sorted_choices)
for choice, option := range sorted_choices {
sortedChoices := choices[groupName]
sort.Sort(sortedChoices)
defaultChoice := defaultChoiceFunc(sortedChoices)
for choice, option := range sortedChoices {
fmt.Println(choice, option)
}
for {
fmt.Printf("%s [%d]: ", group_msg, default_choice)
fmt.Printf("%s [%d]: ", groupMsg, defaultChoice)
text, _ := reader.ReadString('\n')
if text == "\n" {
return sorted_choices[default_choice]
return sortedChoices[defaultChoice]
}
selected, err := strconv.Atoi(strings.TrimSpace(text))
if err != nil {
continue
}
if selected < 0 || selected > len(sorted_choices) {
if selected < 0 || selected > len(sortedChoices) {
continue
}
return sorted_choices[selected]
return sortedChoices[selected]
}
}

func ConfirmUsersChoice(user_choice UserChoice) {
fmt.Println("Platform:", user_choice.Spec.Platform)
fmt.Println("Hypervisor:", user_choice.Spec.Hypervisor)
fmt.Println("Browser and OS:", user_choice.Spec.BrowserOs)
fmt.Println("Download path:", user_choice.DownloadPath)
// ConfirmUsersChoice shows options selected by a user.
func ConfirmUsersChoice(userChoice UserChoice) {
fmt.Println("Platform:", userChoice.Spec.Platform)
fmt.Println("Hypervisor:", userChoice.Spec.Hypervisor)
fmt.Println("Browser and OS:", userChoice.Spec.BrowserOs)
fmt.Println("Download path:", userChoice.DownloadPath)
YesNoConfirmation("Confirm your selection")
}
}
126 changes: 67 additions & 59 deletions utils/data.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
// Data related functions
// Package utils contains various supplementary functions and data structures.
// This file data.go contains functions related to data processing and defines all data structures.
package utils

import (
"encoding/json"
"fmt"
"net/http"
"io/ioutil"
"net/http"
"os"
"path"
"regexp"
"encoding/json"
"strings"
"runtime"
"path"
"os"
"strings"
)

// JsonData represents data obtained by DownloadJson function
// some fields, like _ts, _etag, __colId etc are omitted
type JsonData struct {
// JSONData represents data obtained by DownloadJson function.
// Some fields, like _ts, _etag, __colId etc are omitted.
type JSONData struct {
Active bool `json:"active"`
ID string `json:"id"`
ReleaseNotes string `json:"releaseNotes"`
Expand All @@ -37,50 +38,49 @@ type JsonData struct {
Version string `json:"version"`
}

// Available choices
// Choice type represents list of available choices.
type Choice []string

// Choices grouped by other choices
// ChoiceGroups type represents list of choices grouped by some string key (other choices).
type ChoiceGroups map[string]Choice

// Spec defines possible configuration
// Spec type defines possible configuration available for a user to choose from.
type Spec struct {
Platform string
Hypervisor string
// IE version and Windows version available as a single option
BrowserOs string
// IE version and Windows version available as a single option.
BrowserOs string
}

// VmImage defines from where download virtual machine image and its md5 sum
type VmImage struct {
// VMImage type defines VM archive file metadata.
type VMImage struct {
FileURL string
// instead of actual md5 sum value an URL to a file which contains md5 value is provided
Md5URL string
// Instead of actual md5 sum value Microsoft provides an URL to a file which contains md5 value.
Md5URL string
}

// Available VMs for given Specs
type AvailableVms map[Spec]VmImage
// AvailableVM type represents VMs available for a given Spec.
type AvailableVM map[Spec]VMImage

// Parameters selected by a user
// UserChoice type defines options selected by a user.
type UserChoice struct {
Spec
VmImage
VMImage
DownloadPath string
}

// Default option selector function
// DefaultChoice type defines a function type which is used to calculate default option index.
type DefaultChoice func(choices Choice) int


func (ch Choice) Len() int { return len(ch) }
// Implement Sort interface to make list of choices sortable.
func (ch Choice) Len() int { return len(ch) }
func (ch Choice) Less(i, j int) bool { return ch[i] < ch[j] }
func (ch Choice) Swap(i, j int) { ch[i], ch[j] = ch[j], ch[i] }
func (ch Choice) Swap(i, j int) { ch[i], ch[j] = ch[j], ch[i] }

func DownloadJson(page_url string) []byte {
// page_url contains JSON which is used to build IE version selection menus,
// so the whole page is downloaded and parsed by regexp to extract the actual JSON.
fmt.Printf("Download JSON data from %s\n\n", page_url)
resp, err := http.Get(page_url)
// DownloadJSON function downloads given page and extract JSON structure from it.
func DownloadJSON(pageURL string) []byte {
fmt.Printf("Download JSON data from %s\n\n", pageURL)
resp, err := http.Get(pageURL)
if err != nil {
panic(err)
}
Expand All @@ -95,19 +95,19 @@ func DownloadJson(page_url string) []byte {
return re.FindSubmatch(body)[1]
}

// Parse extracted JSON into more convenient data structures
func ParseJson(raw_data *[]byte) (
platforms, hypervisors, browsers ChoiceGroups, available_vms AvailableVms) {
var data JsonData
if err := json.Unmarshal(*raw_data, &data); err != nil {
// ParseJSON function parses extracted JSON into more convenient data structures.
func ParseJSON(rawData *[]byte) (
platforms, hypervisors, browsers ChoiceGroups, availableVms AvailableVM) {
var data JSONData
if err := json.Unmarshal(*rawData, &data); err != nil {
panic(err)
}

seen_platforms := make(map[string]bool)
seenPlatforms := make(map[string]bool)
platforms = make(ChoiceGroups)
hypervisors = make(ChoiceGroups)
browsers = make(ChoiceGroups)
available_vms = make(AvailableVms)
availableVms = make(AvailableVM)

for _, software := range data.SoftwareList {
hypervisor := software.SoftwareName
Expand All @@ -117,33 +117,33 @@ func ParseJson(raw_data *[]byte) (
}

for _, platform := range software.OsList {
if !seen_platforms[platform] {
seen_platforms[platform] = true
if !seenPlatforms[platform] {
seenPlatforms[platform] = true
platforms["All"] = append(platforms["All"], platform)
}
hypervisors[platform] = append(hypervisors[platform], hypervisor)
}

for _, browser := range software.Vms {
browser_os := strings.Join([]string{browser.BrowserName, browser.OsVersion}, " ")
browsers[hypervisor] = append(browsers[hypervisor], browser_os)
browserOs := strings.Join([]string{browser.BrowserName, browser.OsVersion}, " ")
browsers[hypervisor] = append(browsers[hypervisor], browserOs)
for _, file := range browser.Files {
if file.Md5 != "" {
vm := VmImage{FileURL: file.URL, Md5URL: file.Md5}
vm := VMImage{FileURL: file.URL, Md5URL: file.Md5}
for _, p := range software.OsList {
spec := Spec{Platform: p, Hypervisor: hypervisor, BrowserOs: browser_os}
available_vms[spec] = vm
spec := Spec{Platform: p, Hypervisor: hypervisor, BrowserOs: browserOs}
availableVms[spec] = vm
}
}
}
}
}

return platforms, hypervisors, browsers, available_vms
return platforms, hypervisors, browsers, availableVms
}

// Get default download path based on OS
func get_download_path() string {
// getDownloadPath function constructs default download path based on OS.
func getDownloadPath() string {
switch runtime.GOOS {
case "linux":
return path.Join(os.Getenv("HOME"), "Downloads")
Expand All @@ -156,25 +156,28 @@ func get_download_path() string {
}
}

func get_working_path() string {
working_path, err := os.Getwd()
// getWorkingPath function returns current working path.
func getWorkingPath() string {
workingPath, err := os.Getwd()
if err != nil {
panic(err)
}
return working_path
return workingPath
}


// GetDownloadPaths function builds a list of choices for available download paths.
func GetDownloadPaths() ChoiceGroups {
choices := make(ChoiceGroups)
for _, download_path := range []string{get_working_path(), get_download_path()} {
if download_path != "" {
choices["All"] = append(choices["All"], download_path)
for _, downloadPath := range []string{getWorkingPath(), getDownloadPath()} {
if downloadPath != "" {
choices["All"] = append(choices["All"], downloadPath)
}
}
return choices
}

// GetDefaultPlatform function return an index for current platform from the platforms choices list.
// If no platform detected the first choice is returned (choice indexes are zero-based).
func GetDefaultPlatform(choices Choice) int {
for idx, platform := range choices {
switch {
Expand All @@ -186,9 +189,11 @@ func GetDefaultPlatform(choices Choice) int {
return idx
}
}
return 1
return 0
}

// GetDefaultHypervisor function returns an index for default hypervisor from the hypervisors choices list.
// VirtualBox is now default selection for all platforms but it could be platform specific in the future.
func GetDefaultHypervisor(choices Choice) int {
for idx, hypervisor := range choices {
if hypervisor == "VirtualBox" {
Expand All @@ -198,14 +203,17 @@ func GetDefaultHypervisor(choices Choice) int {
return 1
}

// GetDefaultBrowser function returns an index for default browser.
// The latest browser from the list is considered default for now.
func GetDefaultBrowser(choices Choice) int {
// Consider the latest browser is the newest
return len(choices) - 1
}

// GetDefaultDownloadPath function returns an index for default download folder.
// User's specific download folder is considered default for now.
func GetDefaultDownloadPath(choices Choice) int {
for idx, download_path := range choices {
if strings.Contains(download_path, "Downloads") {
for idx, downloadPath := range choices {
if strings.Contains(downloadPath, "Downloads") {
return idx
}
}
Expand Down
Loading

0 comments on commit 2f23f45

Please sign in to comment.