diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 5bf6c6a3..b5a46784 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,9 +20,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: '^1.20.x' - uses: actions/cache@v2 with: path: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..2b8f9727 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,26 @@ +on: + workflow_dispatch: + push: + branches: + - 'master' + paths-ignore: + - '.idea/..' + - 'docs/**' + pull_request: + paths-ignore: + - '.idea/..' + - 'docs/**' + +name: lint +jobs: + golangci: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v3 + with: + go-version: '^1.20.x' + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.53.2 diff --git a/.gitignore b/.gitignore index 20d17287..badea7ee 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ !*.md !*.iml !*.xml +!*.yml +!*.yaml # Don't ignore Github Actions !.github/workflows/* diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..977d9a8f --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,26 @@ +run: + timeout: 10m +linters: + enable: + - megacheck + - govet + - errcheck + - staticcheck + - unused + - gosimple + - ineffassign + - typecheck + - bodyclose + - rowserrcheck + - asciicheck + - misspell + - prealloc + - exportloopref + - promlinter + - unconvert + - dupl + - goconst + - unused + disable: + - gosec + - lll diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..98133b6e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,8 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/golangci/golangci-lint + rev: v1.53.2 + hooks: + - id: golangci-lint + entry: golangci-lint run --fix diff --git a/go.mod b/go.mod index d31f480f..d0100a56 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,6 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/godbus/dbus/v5 v5.1.0 github.com/google/go-github v17.0.0+incompatible - github.com/grandcat/zeroconf v1.0.0 github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c github.com/hashicorp/go-version v1.6.0 github.com/mgord9518/imgconv v0.0.0-20211227113402-4a8e0ad15713 @@ -35,7 +34,6 @@ require ( require ( github.com/CalebQ42/fuse v0.1.0 // indirect - github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/emirpasic/gods v1.12.0 // indirect github.com/gabriel-vasile/mimetype v1.4.1 // indirect @@ -45,9 +43,9 @@ require ( 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.15.12 // indirect - github.com/miekg/dns v1.1.27 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/rustyoz/Mtransform v0.0.0-20190224104252-60c8c35a3681 // indirect diff --git a/go.sum b/go.sum index 7b64c4ff..50fc2875 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo 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/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= @@ -54,8 +52,6 @@ github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOF github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE= -github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= @@ -75,8 +71,6 @@ 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/mgord9518/imgconv v0.0.0-20211227113402-4a8e0ad15713 h1:XdqgGtorrKq4AgEHVA6H5zYGKWInTMQd69JE4QW9/74= github.com/mgord9518/imgconv v0.0.0-20211227113402-4a8e0ad15713/go.mod h1:nxoRYGVQZklb0OuygCr8Xq4iEYz11MKmG7TaTAQ/3fM= -github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM= -github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 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/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= @@ -153,19 +147,15 @@ go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I= 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.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0= golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 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.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -181,7 +171,6 @@ golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5h 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.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -204,10 +193,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= diff --git a/internal/helpers/appdir.go b/internal/helpers/appdir.go index 5a00fc14..b99d5c64 100644 --- a/internal/helpers/appdir.go +++ b/internal/helpers/appdir.go @@ -22,7 +22,7 @@ func NewAppDir(desktopFilePath string) (AppDir, error) { var ad AppDir // Check if desktop file exists - if Exists(desktopFilePath) == false { + if !Exists(desktopFilePath) { return ad, errors.New("Desktop file not found") } ad.DesktopFilePath = desktopFilePath @@ -54,7 +54,7 @@ func NewAppDir(desktopFilePath string) (AppDir, error) { if err != nil { log.Printf("%v\n", err) } - if strings.HasSuffix(info.Name(), ".desktop") == true { + if strings.HasSuffix(info.Name(), ".desktop") { ad.DesktopFilePath = ad.Path + "/" + info.Name() counter = counter + 1 } @@ -80,7 +80,7 @@ func NewAppDir(desktopFilePath string) (AppDir, error) { return ad, err } - if sect.HasKey("Exec") == false { + if !sect.HasKey("Exec") { err = errors.New("'Desktop Entry' section has no Exec= key") return ad, err } @@ -147,27 +147,32 @@ func (appdir AppDir) CreateIconDirectories() error { // Only use the most common sizes in the hope that at least // those will work on all target systems iconSizes := []int{512, 256, 128, 48, 32, 24, 22, 16, 8} - var err error = nil + var errs []error for _, iconSize := range iconSizes { - err = os.MkdirAll(appdir.Path+"/usr/share/icons/hicolor/"+string(iconSize)+"x"+string(iconSize)+"/apps", 0755) + err := os.MkdirAll(fmt.Sprintf("%s/usr/share/icons/hicolor/%dx%d/apps", appdir.Path, iconSize, iconSize), 0755) + if err != nil { + errs = append(errs, err) + } } - return err + return errors.Join(errs...) } // CopyMainIconToRoot copies the most suitable icon for the // Icon= entry in DesktopFilePath to the root of the AppDir func (appdir AppDir) CopyMainIconToRoot(iconName string) error { - var err error = nil + var errs []error iconPreferenceOrder := []int{128, 256, 512, 48, 32, 24, 22, 16, 8} if Exists(appdir.Path + "/" + iconName + ".png") { log.Println("Top-level icon already exists, leaving untouched") } else { for _, iconSize := range iconPreferenceOrder { - candidate := appdir.Path + "/usr/share/icons/hicolor/" + string(iconSize) + "x" + string(iconSize) + "/apps/" + iconName + ".png" + candidate := fmt.Sprintf("%s/usr/share/icons/hicolor/%dx%d/apps/%s.png", appdir.Path, iconSize, iconSize, iconName) if Exists(candidate) { - CopyFile(candidate, appdir.Path+"/"+iconName+".png") + if err := CopyFile(candidate, appdir.Path+"/"+iconName+".png"); err != nil { + errs = append(errs, err) + } } } } - return err + return errors.Join(errs...) } diff --git a/internal/helpers/desktopfile.go b/internal/helpers/desktopfile.go index 7f11bc8f..cf5f3426 100644 --- a/internal/helpers/desktopfile.go +++ b/internal/helpers/desktopfile.go @@ -14,7 +14,7 @@ func CheckDesktopFile(desktopfile string) error { PrintError("ini.load", err) neededKeys := []string{"Categories", "Name", "Exec", "Type", "Icon"} for _, k := range neededKeys { - if d.Section("Desktop Entry").HasKey(k) == false { + if !d.Section("Desktop Entry").HasKey(k) { return errors.New(".desktop file is missing a '" + k + "'= key\n") } } diff --git a/internal/helpers/git.go b/internal/helpers/git.go index 14a4c238..efa5ca14 100644 --- a/internal/helpers/git.go +++ b/internal/helpers/git.go @@ -18,7 +18,7 @@ func TestGit() { var r *git.Repository var err error - if s.IsDir() == false { + if !s.IsDir() { r, err = git.PlainClone(dir, false, &git.CloneOptions{ URL: "https://github.com/src-d/go-git", Progress: os.Stdout, diff --git a/internal/helpers/helpers.go b/internal/helpers/helpers.go index d09cb92a..9ea7ef00 100644 --- a/internal/helpers/helpers.go +++ b/internal/helpers/helpers.go @@ -179,10 +179,7 @@ func CheckIfFolderExists(filepath string) bool { // Returns true if it does, false otherwise. func CheckIfFileOrFolderExists(filepath string) bool { _, err := os.Stat(filepath) - if os.IsNotExist(err) { - return false - } - return true + return !os.IsNotExist(err) } // CheckIfExecFileExists checks whether a desktop file @@ -219,7 +216,7 @@ func DeleteDesktopFilesWithNonExistingTargets() { for _, file := range files { if strings.HasSuffix(file.Name(), ".desktop") && strings.HasPrefix(file.Name(), "appimagekit_") { exists := CheckIfExecFileExists(xdg.DataHome + "/applications/" + file.Name()) - if exists == false { + if exists { log.Println("Deleting", xdg.DataHome+"/applications/"+file.Name()) e = os.Remove(xdg.DataHome + "/applications/" + file.Name()) LogError("desktop", e) @@ -241,7 +238,7 @@ func GetValuesForAllDesktopFiles(key string) []string { for _, file := range files { if strings.HasSuffix(file.Name(), ".desktop") { exists := CheckIfExecFileExists(xdg.DataHome + "/applications/" + file.Name()) - if exists == true { + if exists { cfg, e := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, // Do not cripple lines hat contain ";" xdg.DataHome+"/applications/"+file.Name()) LogError("GetValuesForAllDesktopFiles", e) @@ -328,7 +325,7 @@ func CheckIfSquashfsVersionSufficient(toolname string) bool { cmd := exec.Command(toolname, "-version") out, err := cmd.CombinedOutput() // Interestingly unsquashfs 4.4 does not return with 0, unlike mksquashfs 4.3 - if strings.Contains(string(out), "version") == false { + if !strings.Contains(string(out), "version") { PrintError(toolname, err) fmt.Printf("%s", string(out)) return false @@ -549,10 +546,7 @@ func CheckForNeededTools(tools []string) error { // IsCommandAvailable returns true if a file is on the $PATH func IsCommandAvailable(name string) bool { _, err := exec.LookPath(name) - if err == nil { - return true - } - return false + return err == nil } // SliceContains returns true if the []string contains string, diff --git a/internal/helpers/opgp.go b/internal/helpers/opgp.go index fe938a73..2393be24 100644 --- a/internal/helpers/opgp.go +++ b/internal/helpers/opgp.go @@ -7,7 +7,6 @@ package helpers import ( "bytes" "encoding/base64" - "errors" "fmt" "log" "strings" @@ -96,19 +95,24 @@ func createKeyPair() { // based on https://stackoverflow.com/a/34008326 func CheckSignature(path string) (*openpgp.Entity, error) { var ent *openpgp.Entity - err := errors.New("could not verify AppImage signature") // Be pessimistic by default, unless we can positively verify the signature pubkeybytes, err := GetSectionData(path, ".sig_key") + if err != nil { + return nil, err + } keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewReader(pubkeybytes)) if err != nil { - return ent, err + return nil, err } sigbytes, err := GetSectionData(path, ".sha256_sig") + if err != nil { + return nil, err + } ent, err = openpgp.CheckArmoredDetachedSignature(keyring, strings.NewReader(CalculateSHA256Digest(path)), bytes.NewReader(sigbytes)) if err != nil { - return ent, err + return nil, err } return ent, nil diff --git a/internal/helpers/updateinformation.go b/internal/helpers/updateinformation.go index fee974c5..15351f79 100644 --- a/internal/helpers/updateinformation.go +++ b/internal/helpers/updateinformation.go @@ -114,17 +114,13 @@ func ValidateUpdateInformation(updateinformation string) error { if detectedTm == "zsync" && u.Scheme == "" { // FIXME: This apparently never triggers, why? return errors.New("Scheme is missing, zsync needs e.,g,. http:// or https://") } - if strings.HasSuffix(u.Path, ".zsync") == false { + if !strings.HasSuffix(u.Path, ".zsync") { return errors.New(updateinformation + " does not end in .zsync") } return nil } -func getChangelogHeadlineForUpdateInformation(updateinformation string) string { - return "" -} - // Taken and modified from // func ReadUpdateInfo(appImagePath string) (string, error) { @@ -137,7 +133,7 @@ func ReadUpdateInfo(appImagePath string) (string, error) { if updInfoSect == nil { return "", errors.New("ELF missing .upd_info section") } - + sectionData, err := updInfoSect.Data() if err != nil { return "", errors.New("unable to read update information from section") diff --git a/src/appimagetool/appdirtool.go b/src/appimagetool/appdirtool.go index 370fc7f7..14fdd149 100644 --- a/src/appimagetool/appdirtool.go +++ b/src/appimagetool/appdirtool.go @@ -240,7 +240,7 @@ func AppDirDeploy(path string) { } // AppRun - if options.libAppRunHooks == false { + if !options.libAppRunHooks { // If libapprun_hooks is not used log.Println("Adding AppRun...") err = os.WriteFile(appdir.Path+"/AppRun", []byte(AppRunData), 0755) @@ -256,12 +256,12 @@ func AppDirDeploy(path string) { qtVersionDetected := 0 - if containsString(allELFs, "libQt5Core.so.5") == true { + if containsString(allELFs, "libQt5Core.so.5") { log.Println("Detected Qt 5") qtVersionDetected = 5 } - if containsString(allELFs, "libQtCore.so.4") == true { + if containsString(allELFs, "libQtCore.so.4") { log.Println("Detected Qt 4") qtVersionDetected = 4 } @@ -281,7 +281,7 @@ func AppDirDeploy(path string) { // and when modifying the ELFs that were pre-existing in the AppDir so that they become aware of the other locations var libraryLocationsInAppDir []string for _, lib := range libraryLocations { - if strings.HasPrefix(lib, appdir.Path) == false { + if !strings.HasPrefix(lib, appdir.Path) { lib = appdir.Path + lib } libraryLocationsInAppDir = helpers.AppendIfMissing(libraryLocationsInAppDir, lib) @@ -310,7 +310,7 @@ func AppDirDeploy(path string) { for _, lib := range allELFs { - deployElf(lib, appdir, err) + deployElf(lib, appdir) patchRpathsInElf(appdir, libraryLocationsInAppDir, lib) if strings.Contains(lib, "libQt5Core.so.5") { @@ -323,7 +323,7 @@ func AppDirDeploy(path string) { func deployFontconfig(appdir helpers.AppDir) error { var err error - if helpers.Exists(appdir.Path+"/etc/fonts") == false { + if !helpers.Exists(appdir.Path + "/etc/fonts") { log.Println("Adding fontconfig symlink... (is this really the right thing to do?)") err = os.MkdirAll(appdir.Path+"/etc/fonts", 0755) if err != nil { @@ -345,7 +345,7 @@ func deployInterpreter(appdir helpers.AppDir) (string, error) { helpers.PrintError("Could not determine ELF interpreter", err) os.Exit(1) } - if helpers.Exists(appdir.Path+"/"+ldLinux) == true { + if helpers.Exists(appdir.Path + "/" + ldLinux) { log.Println("Removing pre-existing", ldLinux+"...") err = syscall.Unlink(appdir.Path + "/" + ldLinux) if err != nil { @@ -427,18 +427,18 @@ func deployInterpreter(appdir helpers.AppDir) (string, error) { // deployElf deploys an ELF (executable or shared library) to the AppDir // if it is not on the exclude list and it is not yet at the target location -func deployElf(lib string, appdir helpers.AppDir, err error) { +func deployElf(lib string, appdir helpers.AppDir) { for _, excludePrefix := range ExcludedLibraries { - if strings.HasPrefix(filepath.Base(lib), excludePrefix) == true && !options.standalone { + if strings.HasPrefix(filepath.Base(lib), excludePrefix) && !options.standalone { log.Println("Skipping", lib, "because it is on the excludelist") return } } log.Println("Working on", lib) - if strings.HasPrefix(lib, appdir.Path) == false { // Do not copy if it is already in the AppDir + if !strings.HasPrefix(lib, appdir.Path) { // Do not copy if it is already in the AppDir libTargetPath := appdir.Path + "/" + lib - if options.libAppRunHooks && checkWhetherPartOfLibc(lib) == true { + if options.libAppRunHooks && checkWhetherPartOfLibc(lib) { // This file is part of the libc family of libraries and we want to use libapprun_hooks, // hence copy to a separate directory unlike the rest of the libraries. The reason is // that this familiy of libraries will only be used by libapprun_hooks if the @@ -449,8 +449,7 @@ func deployElf(lib string, appdir helpers.AppDir, err error) { } log.Println("Copying to libTargetPath:", libTargetPath) - err = helpers.CopyFile(lib, libTargetPath) // If libapprun_hooks is not used - + err := helpers.CopyFile(lib, libTargetPath) // If libapprun_hooks is not used if err != nil { log.Println(libTargetPath, "could not be copied:", err) os.Exit(1) @@ -464,11 +463,11 @@ func patchQtPrfxpath(appdir helpers.AppDir, lib string, libraryLocationsInAppDir log.Println("Patching qt_prfxpath, otherwise can't load platform plugin...") f, err := os.Open(appdir.Path + "/" + lib) // Open file for reading/determining the offset - defer f.Close() if err != nil { helpers.PrintError("Could not open libQt5Core.so.5 for reading", err) os.Exit(1) } + defer f.Close() f.Seek(0, 0) // Search from the beginning of the file search := []byte("qt_prfxpath=") @@ -507,14 +506,14 @@ func patchQtPrfxpath(appdir helpers.AppDir, lib string, libraryLocationsInAppDir } f, err = os.OpenFile(appdir.Path+"/"+lib, os.O_WRONLY, 0644) // Open file writable, why is this so complicated - defer f.Close() if err != nil { helpers.PrintError("Could not open libQt5Core.so.5 for writing", err) os.Exit(1) } + defer f.Close() // Now that we know where in the file the information is, go write it f.Seek(offset, 0) - if quirksModePatchQtPrfxPath == false { + if !quirksModePatchQtPrfxPath { log.Println("Patching qt_prfxpath in libQt5Core.so.5 to " + relPathToQt) _, err = f.Write([]byte(relPathToQt + "\x00")) } else { @@ -534,14 +533,14 @@ func deployCopyrightFiles(appdir helpers.AppDir) { shouldDoIt := true for _, excludePrefix := range ExcludedLibraries { - if strings.HasPrefix(filepath.Base(lib), excludePrefix) == true && options.standalone == false { + if strings.HasPrefix(filepath.Base(lib), excludePrefix) && !options.standalone { log.Println("Skipping copyright file for ", lib, "because it is on the excludelist") shouldDoIt = false break } } - if shouldDoIt == true && strings.HasPrefix(lib, appdir.Path) == false { + if shouldDoIt && !strings.HasPrefix(lib, appdir.Path) { // Copy copyright files into the AppImage copyrightFile, err := getCopyrightFile(lib) // It is perfectly fine for this to error - on non-dpkg systems, or if lib was not in a deb package @@ -553,12 +552,12 @@ func deployCopyrightFiles(appdir helpers.AppDir) { } } log.Println("Done") - if options.standalone == true { + if options.standalone { log.Println("To check whether it is really self-contained, run:") fmt.Println("LD_LIBRARY_PATH='' find " + appdir.Path + " -type f -exec ldd {} 2>&1 \\; | grep '=>' | grep -v " + appdir.Path) } - if options.libAppRunHooks == true { + if options.libAppRunHooks { log.Println("The option '-m' was used. Hence, you need to manually add AppRun, .env, and libapprun_hooks.so") log.Println("from https://github.com/AppImageCrafters/AppRun/releases/tag/continuous. TODO: Automate this") } @@ -718,11 +717,11 @@ func handleGStreamer(appdir helpers.AppDir) { func patchRpathsInElf(appdir helpers.AppDir, libraryLocationsInAppDir []string, path string) { - if strings.HasPrefix(path, appdir.Path) == false { + if !strings.HasPrefix(path, appdir.Path) { path = filepath.Clean(appdir.Path + "/" + path) } var newRpathStringForElf string - var newRpathStrings []string + newRpathStrings := make([]string, 0, len(libraryLocationsInAppDir)) for _, libloc := range libraryLocationsInAppDir { relpath, err := filepath.Rel(filepath.Dir(path), libloc) if err != nil { @@ -738,19 +737,19 @@ func patchRpathsInElf(appdir helpers.AppDir, libraryLocationsInAppDir []string, return } - if strings.HasPrefix(filepath.Base(path), "ld-") == true { + if strings.HasPrefix(filepath.Base(path), "ld-") { log.Println("Not writing rpath in", path, "because its name starts with ld-...") return } // Be sure that the file we want to patch exists - if helpers.Exists(path) == false { + if !helpers.Exists(path) { log.Println(path, "does not exist, hence we cannot set its rpath, exiting") os.Exit(1) } // Call patchelf to set the rpath - if helpers.Exists(path) == true { + if helpers.Exists(path) { // log.Println("Rewriting rpath of", path) cmd := exec.Command("patchelf", "--set-rpath", newRpathStringForElf, path) // log.Println(cmd.Args) @@ -836,7 +835,7 @@ func appendLib(path string) { for _, rpath := range rpaths { rpath = filepath.Clean(strings.Replace(rpath, "$ORIGIN", filepath.Dir(path), -1)) - if helpers.SliceContains(libraryLocations, rpath) == false && rpath != "" { + if !helpers.SliceContains(libraryLocations, rpath) && rpath != "" { log.Println("Add", rpath, "to the libraryLocations directories we search for libraries") libraryLocations = helpers.AppendIfMissing(libraryLocations, filepath.Clean(rpath)) } @@ -859,7 +858,7 @@ func determineELFsInDirTree(appdir helpers.AppDir, pathToDirTreeToBeDeployed str appendLib(lib) } - var allELFsUnderPath []ELF + allELFsUnderPath := make([]ELF, 0, len(allelfs)) for _, elfpath := range allelfs { elfobj := ELF{} elfobj.path = elfpath @@ -905,13 +904,13 @@ func findAllExecutablesAndLibraries(path string) ([]string, error) { // fmt.Println(" findAllExecutablesAndLibrarieschecking", path) - // If we have a file, then there is nothing to walk and we can return it directly - if helpers.IsDirectory(path) != true { + // If we have a file, then there is nothing to walk, and we can return it directly + if !helpers.IsDirectory(path) { allExecutablesAndLibraries = append(allExecutablesAndLibraries, path) return allExecutablesAndLibraries, nil } - filepath.Walk(path, func(path string, info os.FileInfo, e error) error { + if err := filepath.Walk(path, func(path string, info os.FileInfo, e error) error { if e != nil { return e } @@ -919,23 +918,28 @@ func findAllExecutablesAndLibraries(path string) ([]string, error) { // Add ELF files if info.Mode().IsRegular() { f, err := os.Open(path) + if err != nil { + return err + } defer f.Close() if err == nil { - if helpers.CheckMagicAtOffset(f, "454c46", 1) == true { + if helpers.CheckMagicAtOffset(f, "454c46", 1) { allExecutablesAndLibraries = helpers.AppendIfMissing(allExecutablesAndLibraries, path) } } } return nil - }) + }); err != nil { + return nil, err + } return allExecutablesAndLibraries, nil } func getDeps(binaryOrLib string) error { var libs []string - if helpers.Exists(binaryOrLib) == false { + if !helpers.Exists(binaryOrLib) { return errors.New("binary does not exist: " + binaryOrLib) } @@ -954,7 +958,7 @@ func getDeps(binaryOrLib string) error { if err != nil { return err } - if helpers.SliceContains(allELFs, s) == true { + if helpers.SliceContains(allELFs, s) { continue } else { libPath, err := findLibrary(lib) @@ -1094,7 +1098,9 @@ func PatchFile(path string, search string, replace string) error { return err } - os.Rename(path+".patched", path) + if err := os.Rename(path+".patched", path); err != nil { + return err + } return nil } @@ -1102,18 +1108,18 @@ func getCopyrightFile(path string) (string, error) { var copyrightFile string - if helpers.IsCommandAvailable("dpkg") == false { + if !helpers.IsCommandAvailable("dpkg") { return copyrightFile, errors.New("dpkg not found, hence not deploying copyright files") } - if helpers.IsCommandAvailable("dpkg-query") == false { + if !helpers.IsCommandAvailable("dpkg-query") { return copyrightFile, errors.New("dpkg-query not found, hence not deploying copyright files") } // Find out which package the file being deployed belongs to var packageContainingTheSO string pkg, ok := packagesContainingFiles[path] - if ok == true { + if ok { packageContainingTheSO = pkg } else { cmd := exec.Command("dpkg", "-S", path) @@ -1130,7 +1136,7 @@ func getCopyrightFile(path string) (string, error) { // We are caching the results so that multiple packages belonging to the same package have to run dpkg-query only once // So first we check whether we already know it cf, ok := copyrightFiles[packageContainingTheSO] - if ok == true { + if ok { return cf, nil } @@ -1172,13 +1178,13 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { } f, err := os.Open(library) - defer f.Close() if err != nil { helpers.PrintError("Could not open libQt5Core.so.5", err) os.Exit(1) } + defer f.Close() - qtPrfxpath := getQtPrfxpath(f, err, qtVersion) + qtPrfxpath := getQtPrfxpath(f, qtVersion) if qtPrfxpath == "" { log.Println("Got empty qtPrfxpath, exiting") @@ -1187,7 +1193,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { log.Println("Looking in", qtPrfxpath+"/plugins") - if helpers.Exists(qtPrfxpath+"/plugins/platforms/libqxcb.so") == false { + if !helpers.Exists(qtPrfxpath + "/plugins/platforms/libqxcb.so") { log.Println("Could not find 'plugins/platforms/libqxcb.so' in qtPrfxpath, exiting") os.Exit(1) } @@ -1211,7 +1217,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // iconengines and imageformats, if Qt5Gui.so.5 is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1259 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5Gui.so.5") == true { + if strings.HasSuffix(lib, "libQt5Gui.so.5") { if helpers.Exists(qtPrfxpath + "/plugins/iconengines/") { determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/iconengines/") } else { @@ -1229,10 +1235,10 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // Platform OpenGL context, if one of several libraries is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1282 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5Gui.so.5") == true || - strings.HasSuffix(lib, "libQt5OpenGL.so.5") == true || - strings.HasSuffix(lib, "libQt5XcbQpa.so.5") == true || - strings.HasSuffix(lib, "libxcb-glx.so") == true { + if strings.HasSuffix(lib, "libQt5Gui.so.5") || + strings.HasSuffix(lib, "libQt5OpenGL.so.5") || + strings.HasSuffix(lib, "libQt5XcbQpa.so.5") || + strings.HasSuffix(lib, "libxcb-glx.so") { { determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/xcbglintegrations/") break @@ -1243,7 +1249,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // CUPS print support plugin, if libQt5PrintSupport.so.5 is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1299 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5PrintSupport.so.5") == true { + if strings.HasSuffix(lib, "libQt5PrintSupport.so.5") { determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/printsupport/libcupsprintersupport.so") break } @@ -1252,7 +1258,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // Network bearers, if libQt5Network.so.5 is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1304 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5Network.so.5") == true { + if strings.HasSuffix(lib, "libQt5Network.so.5") { determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/bearer/") break } @@ -1261,7 +1267,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // Sql drivers, if libQt5Sql.so.5 is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1312 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5Sql.so.5") == true { + if strings.HasSuffix(lib, "libQt5Sql.so.5") { determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/sqldrivers/") break } @@ -1270,7 +1276,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // Positioning plugins, if libQt5Positioning.so.5 is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1320 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5Positioning.so.5") == true { + if strings.HasSuffix(lib, "libQt5Positioning.so.5") { determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/position/") break } @@ -1279,7 +1285,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // Multimedia plugins, if libQt5Multimedia.so.5 is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1328 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5Multimedia.so.5") == true { + if strings.HasSuffix(lib, "libQt5Multimedia.so.5") { determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/mediaservice/") determineELFsInDirTree(appdir, qtPrfxpath+"/plugins/audio/") break @@ -1289,7 +1295,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { // WebEngine, if libQt5WebEngineCore.so.5 is about to be deployed // similar to https://github.com/probonopd/linuxdeployqt/blob/42e51ea7c7a572a0aa1a21fc47d0f80032809d9d/tools/linuxdeployqt/shared.cpp#L1343 for _, lib := range allELFs { - if strings.HasSuffix(lib, "libQt5WebEngineCore.so.5") == true { + if strings.HasSuffix(lib, "libQt5WebEngineCore.so.5") { log.Println("TODO: Deploying Qt5WebEngine components...") os.Exit(1) @@ -1388,7 +1394,7 @@ func handleQt(appdir helpers.AppDir, qtVersion int) { } } -func getQtPrfxpath(f *os.File, err error, qtVersion int) string { +func getQtPrfxpath(f *os.File, qtVersion int) string { f.Seek(0, 0) // Search from the beginning of the file search := []byte("qt_prfxpath=") @@ -1403,7 +1409,7 @@ func getQtPrfxpath(f *os.File, err error, qtVersion int) string { f.Seek(offset, 0) buf := make([]byte, length) // Make a buffer that is exactly as long as the range we want to read - _, err = io.ReadFull(f, buf) + _, err := io.ReadFull(f, buf) if err != nil { helpers.PrintError("Unable to read qt_prfxpath", err) os.Exit(1) @@ -1419,7 +1425,7 @@ func getQtPrfxpath(f *os.File, err error, qtVersion int) string { // Some distributions, including Ubuntu and Alpine, // have qt_prfxpath set to '/usr' but the files are actually in e.g., '/usr/lib/qt5' // In this case, we should NOT patch it - if helpers.IsDirectory(qt_prfxpath+"/plugins") == false { + if !helpers.IsDirectory(qt_prfxpath + "/plugins") { log.Println("Got qt_prfxpath but it does not contain 'plugins'") results := helpers.FilesWithSuffixInDirectoryRecursive(qt_prfxpath, "libqxcb.so") log.Println("libqxcb.so found:", results) diff --git a/src/appimagetool/appimagetool.go b/src/appimagetool/appimagetool.go index a3fddc2a..96f2580a 100644 --- a/src/appimagetool/appimagetool.go +++ b/src/appimagetool/appimagetool.go @@ -42,7 +42,7 @@ func checkRunningWithinDocker() bool { res, err := os.ReadFile("/proc/1/cgroup") if err == nil { // Do not exit if os.ReadFile("/proc/1/cgroup") fails. This happens, e.g., on FreeBSD - if strings.HasPrefix(string(res), "/lxc") || strings.HasPrefix(string(res), "/docker") || helpers.Exists("/.dockerenv") == true { + if strings.HasPrefix(string(res), "/lxc") || strings.HasPrefix(string(res), "/docker") || helpers.Exists("/.dockerenv") { log.Println("Running inside Docker. Please make sure that the environment variables from Travis CI") log.Println("available inside Docker if you are running on Travis CI.") log.Println("This can be achieved by using something along the lines of 'docker run --env-file <(env)'.") @@ -213,13 +213,13 @@ func GenerateAppImage( if err != nil { helpers.PrintError("Determine architecture", err) return err - } else if info.IsDir() == false && strings.Contains(info.Name(), ".so.") { + } else if !info.IsDir() && strings.Contains(info.Name(), ".so.") { arch, err := helpers.GetElfArchitecture(path) if err != nil { // we received an error when analyzing the arch helpers.PrintError("Determine architecture", err) return err - } else if helpers.SliceContains(archs, arch) == false { + } else if !helpers.SliceContains(archs, arch) { log.Println("Architecture of", info.Name()+":", arch) archs = helpers.AppendIfMissing(archs, arch) } else { @@ -274,7 +274,7 @@ func GenerateAppImage( // check the parent directory exists targetDir := filepath.Dir(destination) if !helpers.CheckIfFolderExists(targetDir) { - log.Fatal(fmt.Sprintf("%s does not exist", targetDir)) + log.Fatalf("%s does not exist", targetDir) return } // the parent directory exists. Make a fullpath to the destination appimage @@ -301,7 +301,10 @@ func GenerateAppImage( // Check if we find a png matching the Icon= key in various locations // We insist on a png because otherwise we need to costly convert it to png at integration time // since thumbails need to be in png format - supportedIconExtensions := []struct {ext string; warning string}{ + supportedIconExtensions := []struct { + ext string + warning string + }{ {".png", ""}, {".svg", "SVG support is optional"}, {".xpm", "XPM icons are deprecated"}, @@ -314,7 +317,7 @@ func GenerateAppImage( for _, extension := range supportedIconExtensions { for _, location := range locations { filename := location + iconname + extension.ext - if helpers.CheckIfFileExists(filename) == true { + if helpers.CheckIfFileExists(filename) { iconfile = filename break } @@ -340,7 +343,7 @@ func GenerateAppImage( // TODO: Check validity and size of png" // Deleting pre-existing .DirIcon - if helpers.CheckIfFileExists(appdir+"/.DirIcon") == true { + if helpers.CheckIfFileExists(appdir + "/.DirIcon") { log.Println("Deleting pre-existing .DirIcon") _ = os.Remove(appdir + "/.DirIcon") } @@ -367,7 +370,7 @@ func GenerateAppImage( appstreamfile := appdir + "/usr/share/metainfo/" + strings.Replace(filepath.Base(desktopfile), ".desktop", ".appdata.xml", -1) if !checkAppStreamMetadata { log.Println("WARNING: Skipping AppStream metadata check...") - } else if helpers.CheckIfFileExists(appstreamfile) == false { + } else if !helpers.CheckIfFileExists(appstreamfile) { log.Println("WARNING: AppStream upstream metadata is missing, please consider creating it in") fmt.Println(" " + appstreamfile) fmt.Println(" Please see https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html#sect-Quickstart-DesktopApps") @@ -393,13 +396,13 @@ func GenerateAppImage( runtimeDir = helpers.Here() } runtimeFile = runtimeDir + "/runtime-" + arch - if helpers.CheckIfFileExists(runtimeFile) == false { + if !helpers.CheckIfFileExists(runtimeFile) { log.Println("Cannot find " + runtimeFile + ", exiting") log.Println("It should have been bundled, but you can get it from https://github.com/AppImage/AppImageKit/releases/continuous") // TODO: Download it from there? os.Exit(1) } - } else if helpers.CheckIfFileExists(runtimeFile) == false { + } else if !helpers.CheckIfFileExists(runtimeFile) { log.Println("Cannot find " + runtimeFile + ", exiting") os.Exit(1) } @@ -461,7 +464,7 @@ func GenerateAppImage( _ = os.Chmod(target, 0755) // Get the filesize in bytes of the resulting AppImage - fi, err = os.Stat(target) + _, err = os.Stat(target) if err != nil { helpers.PrintError("Could not get size of AppImage", err) os.Exit(1) @@ -498,7 +501,7 @@ func GenerateAppImage( fmt.Println("Running on Travis CI") if os.Getenv("TRAVIS_PULL_REQUEST") != "false" { fmt.Println("Will not calculate update information for GitHub because this is a pull request") - } else if ghTokenFound == false || ghToken == "" { + } else if !ghTokenFound || ghToken == "" { fmt.Println("Will not calculate update information for GitHub because $GITHUB_TOKEN is missing") fmt.Println("please set it in the Travis CI Repository Settings for this project.") fmt.Println("You can get one from https://github.com/settings/tokens") @@ -587,9 +590,9 @@ func GenerateAppImage( // The actual signing // Decrypt the private key which we need for signing - if helpers.CheckIfFileExists(helpers.EncPrivkeyFileName) == true { + if helpers.CheckIfFileExists(helpers.EncPrivkeyFileName) { _, ok := os.LookupEnv(helpers.EnvSuperSecret) - if ok != true { + if !ok { fmt.Println("Environment variable", helpers.EnvSuperSecret, "not present, cannot sign") os.Exit(1) } @@ -614,7 +617,7 @@ func GenerateAppImage( } // Sign the AppImage - if helpers.CheckIfFileExists(helpers.PrivkeyFileName) == true { + if helpers.CheckIfFileExists(helpers.PrivkeyFileName) { fmt.Println("Attempting to sign the AppImage...") err = helpers.SignAppImage(target, digest) if err != nil { @@ -656,7 +659,7 @@ func GenerateAppImage( zsync.ZsyncMake(target, opts) // Check if the zsync file is really there - fi, err = os.Stat(target + ".zsync") + _, err = os.Stat(target + ".zsync") if err != nil { helpers.PrintError("zsync file not generated", err) os.Exit(1) diff --git a/src/appimagetool/cli.go b/src/appimagetool/cli.go index 2da30527..d4ab7746 100644 --- a/src/appimagetool/cli.go +++ b/src/appimagetool/cli.go @@ -20,7 +20,8 @@ var Sections = []string{".upd_info", ".sha256_sig", ".sig_key", ".digest_md5"} // bootstrapAppImageDeploy wrapper function to deploy an AppImage // from Desktop file -// Args: c: cli.Context +// +// Args: c: cli.Context func bootstrapAppImageDeploy(c *cli.Context) error { // make sure the user provided one and one only desktop if c.NArg() != 1 { @@ -38,7 +39,8 @@ func bootstrapAppImageDeploy(c *cli.Context) error { } // bootstrapValidateAppImage wrapper function to validate a AppImage -// Args: c: cli.Context +// +// Args: c: cli.Context func bootstrapValidateAppImage(c *cli.Context) error { // make sure that we received only 1 file path @@ -73,20 +75,22 @@ func bootstrapValidateAppImage(c *cli.Context) error { log.Println("KeyId:", ent.PrimaryKey.KeyId) log.Println("Fingerprint:", ent.PrimaryKey.Fingerprint) - // happily ever after! no errors occured + // happily ever after! no errors occurred return nil } // bootstrapSetupSigning wrapper function to setup signing in // the current Git repository -// Args: c: cli.Context +// +// Args: c: cli.Context func bootstrapSetupSigning(c *cli.Context) error { return setupSigning(c.Bool("overwrite")) } // bootstrapAppImageSections is a function which converts cli.Context to // string based arguments. Wrapper function to show the sections of the AppImage -// Args: c: cli.Context +// +// Args: c: cli.Context func bootstrapAppImageSections(c *cli.Context) error { // check if the number of arguments are stictly 1, if not // return @@ -135,7 +139,8 @@ func bootstrapAppImageSections(c *cli.Context) error { // check if all the necessary dependencies exist, // finally check if the provided argument, AppDir is a directly. // Call GenerateAppImage with the converted arguments -// Args: c: cli.Context +// +// Args: c: cli.Context func bootstrapAppImageBuild(c *cli.Context) error { // check if the number of arguments are stictly 1, if not @@ -220,7 +225,7 @@ func main() { // Add the location of the executable to the $PATH helpers.AddHereToPath() - + // fmt.Println("PATH:", os.Getenv("PATH")) // Check for needed files on $PATH @@ -231,12 +236,12 @@ func main() { if err != nil { os.Exit(1) } - + // Check whether we have a sufficient version of mksquashfs for -offset - if helpers.CheckIfSquashfsVersionSufficient("mksquashfs") == false { + if !helpers.CheckIfSquashfsVersionSufficient("mksquashfs") { os.Exit(1) } - + // define subcommands, like 'deploy', 'validate', ... app.Commands = []*cli.Command{ { diff --git a/src/appimagetool/setupsigning.go b/src/appimagetool/setupsigning.go index 675a7de5..0eb7ed2e 100644 --- a/src/appimagetool/setupsigning.go +++ b/src/appimagetool/setupsigning.go @@ -13,6 +13,7 @@ package main import ( "bufio" "context" + "errors" "fmt" "math/rand" "os" @@ -32,47 +33,44 @@ func setupSigning(overwriteSecretFiles bool) error { cwd, err := os.Getwd() if err != nil { - fmt.Println("os.Getwd:", err) - os.Exit(1) + return err } gitRepo, err = git.PlainOpenWithOptions(cwd, &git.PlainOpenOptions{DetectDotGit: true}) if err != nil { - fmt.Println("git:", err) - } - - if gitRepo == nil { - fmt.Println("Could not open git repository at", cwd+". \nPlease execute this command from within a clean git repository.") - os.Exit(1) + return err } gitWorktree, _ := gitRepo.Worktree() s, _ := gitWorktree.Status() clean := s.IsClean() - if clean == false { - fmt.Println("Repository is not clean. Please commit or stash any changes first.") - os.Exit(1) - + if !clean { + return errors.New("Repository is not clean. Please commit or stash any changes first.") } // Check for needed files on $PATH tools := []string{"sh", "git", "openssl"} err = helpers.CheckForNeededTools(tools) if err != nil { - os.Exit(1) + return err } // Exit if the repo already contains the files we are about to add - exitIfFileExists(helpers.PubkeyFileName, "Public key", overwriteSecretFiles) - exitIfFileExists(helpers.PrivkeyFileName, "Private key", overwriteSecretFiles) - exitIfFileExists(helpers.EncPrivkeyFileName, "Encrypted private key", overwriteSecretFiles) + if err := exitIfFileExists(helpers.PubkeyFileName, "Public key", overwriteSecretFiles); err != nil { + return err + } + if err := exitIfFileExists(helpers.PrivkeyFileName, "Private key", overwriteSecretFiles); err != nil { + return err + } + if err := exitIfFileExists(helpers.EncPrivkeyFileName, "Encrypted private key", overwriteSecretFiles); err != nil { + return err + } // Get repo_slug. gitRemote, err := gitRepo.Remote("origin") if err != nil { - fmt.Println("Could not get git remote") - os.Exit(1) + return err } components := strings.Split(gitRemote.Config().URLs[0], "/") repoSlug := components[len(components)-2] + "/" + components[len(components)-1] @@ -85,7 +83,10 @@ func setupSigning(overwriteSecretFiles bool) error { fmt.Println("The GitHub token is used to store the decryption password") fmt.Println("for the private signing key as private variable on Travis CI") fmt.Print("Enter GitHub token: ") - text, _ := reader.ReadString('\n') + text, err := reader.ReadString('\n') + if err != nil { + return err + } token := strings.TrimSpace(text) // fmt.Println(token) @@ -93,7 +94,7 @@ func setupSigning(overwriteSecretFiles bool) error { fmt.Println("Is your repository on travis.com? Answer 'no' if org (yes/no)") var client *travis.Client var travisSettingsURL string - if AskForConfirmation() == true { + if AskForConfirmation() { fmt.Println("Assuming your repository is on travis.com") client = travis.NewClient(travis.ApiComUrl, token) travisSettingsURL = "https://travis-ci.com/" + repoSlug + "/settings" @@ -106,20 +107,19 @@ func setupSigning(overwriteSecretFiles bool) error { // Read existing environment variables on Travis CI esList, resp, err := client.EnvVars.ListByRepoSlug(context.Background(), repoSlug) if err != nil { - fmt.Println("client.EnvVars.ListByRepoSlug:", err) - os.Exit(1) + return err } if resp.StatusCode < 200 || 300 <= resp.StatusCode { fmt.Printf("Could not read existing environment variables on Travis CI for repo %s: invalid http status: %s", repoSlug, resp.Status) } - var existingVars []string + existingVars := make([]string, 0, len(esList)) for _, e := range esList { // fmt.Println("* Name:", *e.Name, "Public:", *e.Public, "Id:", *e.Id) existingVars = append(existingVars, *e.Name) } - if Contains(existingVars, helpers.EnvSuperSecret) == true { + if Contains(existingVars, helpers.EnvSuperSecret) { fmt.Println("Environment variable", helpers.EnvSuperSecret, "already exists on Travis CI") fmt.Println("You can check it on", travisSettingsURL) fmt.Println("It looks like this repository is already set up for signing. Exiting") @@ -138,22 +138,12 @@ func setupSigning(overwriteSecretFiles bool) error { // Check if we succeeded until here if _, err := os.Stat(helpers.PrivkeyFileName); err != nil { - fmt.Println("Could not create private key, exiting") - os.Exit(1) + return err } // Check if password/secret already exists, delete it if -o was specified, exit otherwise - if _, err := os.Stat("secret"); err == nil { - if !overwriteSecretFiles { - fmt.Println("Secret already exists, exiting") - os.Exit(1) - } else { - err := os.Remove("secret") - if err != nil { - fmt.Println(err) - os.Exit(1) - } - } + if err := exitIfFileExists("secret", "Secret", overwriteSecretFiles); err != nil { + return err } // Generate the password which we will store as a @@ -162,14 +152,12 @@ func setupSigning(overwriteSecretFiles bool) error { superSecretPassword := generatePassword() f, err := os.Create("secret") if err != nil { - fmt.Println("Could not open file for writing secret, exiting") - os.Exit(1) + return err } defer f.Close() _, err = f.WriteString(superSecretPassword) if err != nil { - fmt.Println("Could not write secret, exiting") - os.Exit(1) + return err } // Encrypt the private key using the password @@ -177,14 +165,12 @@ func setupSigning(overwriteSecretFiles bool) error { cmd := "openssl aes-256-cbc -pass file:./secret -in ./" + helpers.PrivkeyFileName + " -out ./" + helpers.EncPrivkeyFileName + " -a" err = helpers.RunCmdStringTransparently(cmd) if err != nil { - fmt.Println("Could not encrypt the private key using the password, exiting") - os.Exit(1) + return err } // Check if we succeeded until here if _, err := os.Stat(helpers.EncPrivkeyFileName); err != nil { - fmt.Println("Could not encrypt private key, exiting") - os.Exit(1) + return err } // Delete unneeded public key @@ -208,14 +194,12 @@ func setupSigning(overwriteSecretFiles bool) error { _, err = gitWorktree.Add(helpers.EncPrivkeyFileName) if err != nil { - fmt.Println("Could not add encrypted private key to git repository") - os.Exit(1) + return err } _, err = gitWorktree.Add(helpers.PubkeyFileName) if err != nil { - fmt.Println("Could not add public key to git repository") - os.Exit(1) + return err } // TODO: Can we automate this? @@ -236,14 +220,13 @@ func setupSigning(overwriteSecretFiles bool) error { */ fmt.Println("Then, run 'git commit' and 'git push'") - // FIXME: Use real error raising return nil } // SetTravisEnv sets a private variable on Travis CI func SetTravisEnv(client *travis.Client, repoSlug string, existingVars []string, name string, value string, travisSettingsURL string) { body := travis.EnvVarBody{Name: name, Value: value, Public: false} - if Contains(existingVars, name) == false { + if !Contains(existingVars, name) { fmt.Println("Set environment variable", name, "on Travis CI...") _, resp, err := client.EnvVars.CreateByRepoSlug(context.Background(), repoSlug, &body) if err != nil { @@ -267,20 +250,22 @@ func Contains(s []string, e string) bool { return false } +var ErrEarlyExit = errors.New("early exit") + // exitIfFileExists checks if file already exists, deletes it if -o was specified, exit otherwise -func exitIfFileExists(file string, description string, overwriteSecretFile bool) { +func exitIfFileExists(file string, description string, overwriteSecretFile bool) error { if _, err := os.Stat(file); err == nil { if !overwriteSecretFile { fmt.Println(description, "'"+file+"'", "already exists, exiting") - os.Exit(1) + return ErrEarlyExit } else { err := os.Remove(file) if err != nil { - fmt.Println(err) - os.Exit(1) + return err } } } + return nil } //////////////////////////////// start AskForConfirmation @@ -309,22 +294,11 @@ func AskForConfirmation() bool { } } -// posString returns the first index of element in slice. -// If slice does not contain element, returns -1. -func posString(slice []string, element string) int { - for index, elem := range slice { - if elem == element { - return index - } - } - return -1 -} - // containsString returns true iff slice contains element that ends with the given string func containsString(slice []string, element string) bool { for _, item := range slice { - if strings.HasSuffix(item, element) == true { + if strings.HasSuffix(item, element) { return true } } @@ -332,7 +306,7 @@ func containsString(slice []string, element string) bool { return false } -//////////////////////////////// end AskForConfirmation +// ////////////////////////////// end AskForConfirmation // TODO: Please fix this extremely dangerous way of generating passwords // generatePassword generates a random password consisting // consisting of letters, numbers, and selected special characters diff --git a/src/mkappimage/mkappimage.go b/src/mkappimage/mkappimage.go index 97826472..906344de 100644 --- a/src/mkappimage/mkappimage.go +++ b/src/mkappimage/mkappimage.go @@ -38,7 +38,8 @@ func listLongFilesInAppImage(path string) { // check if all the necessary dependencies exist, // finally check if the provided argument, AppDir is a directly. // Call GenerateAppImage with the converted arguments -// Args: c: cli.Context +// +// Args: c: cli.Context func bootstrapMkAppImage(c *cli.Context) error { // check if the number of arguments are stictly 1, if not @@ -55,7 +56,7 @@ func bootstrapMkAppImage(c *cli.Context) error { helpers.AddHereToPath() // Check whether we have a sufficient version of mksquashfs for -offset - if helpers.CheckIfSquashfsVersionSufficient("mksquashfs") == false { + if !helpers.CheckIfSquashfsVersionSufficient("mksquashfs") { os.Exit(1) }