From 3e1eb01e248ebbc314b8b9f50bbc371ac8df666b Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sat, 22 May 2021 18:37:49 +0100 Subject: [PATCH 01/10] feat(build)!: add ability to output as directory and/or archive This changes the filename pattern of the resulting archive, for example: Old: Emacs.app-[master][2021-05-19][6ae3f7e][macOS-11.3][x86_64].tbz New: Emacs.2021-05-19.6ae3f7e.master.macOS-11-3.x86_64.tbz Emacs.app also resides within a folder in the archive now instead of the in the root. For the above example, the path to Emacs.app within the archive would be: Emacs.2021-05-19.6ae3f7e.master.macOS-11-3.x86_64/Emacs.app Archive creation can also be skipped by passing in --no-archive, which will instead leave a build folder with the same name as the archive. If you want to keep the build directory, and also a create archive, pass in --archive-keep-build-dir. BREAKING CHANGE: New archive naming convention, and folder structure within archive. --- README.md | 5 ++ build-emacs-for-macos | 114 +++++++++++++++++++++++++++++++++++------- 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index b29ed04..3389857 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,11 @@ Options: --no-frame-refocus Apply no-frame-refocus patch (default: disabled) --[no-]github-auth Make authenticated GitHub API requests if GITHUB_TOKEN environment variable is set.(default: enabled) --work-dir DIR Specify a working directory where tarballs, sources, and builds will be stored and worked with + -o, --output DIR Output directory for finished builds (default: /builds) + --build-name NAME Override generated build name + --dist-include x,y,z List of extra files to copy from Emacs source into build folder/archive (default: COPYING) + --[no-]archive Enable/disable creating *.tbz archive (default: enabled) + --[no-]archive-keep Enable/disable keeping source folder for archive (default: disabled) --plan FILE Follow given plan file, instead of using given git ref/sha ``` diff --git a/build-emacs-for-macos b/build-emacs-for-macos index 2e22fbd..d8b970f 100755 --- a/build-emacs-for-macos +++ b/build-emacs-for-macos @@ -101,13 +101,15 @@ class Build detect_native_comp if options[:native_comp].nil? app = compile_source(@source_dir) + build_dir, app = create_build_dir(app) + symlink_internals(app) add_cli_helper(app) LibEmbedder.new(app, brew_dir, extra_libs).embed GccLibEmbedder.new(app, gcc_info).embed if options[:native_comp] - archive_app(app) + archive_build(build_dir) if options[:archive] end private @@ -120,7 +122,16 @@ class Build ref: plan.dig('commit', 'ref'), date: plan.dig('commit', 'date') } - @archive_filename = plan['archive'] + + if plan.dig('output', 'directory') + @output_dir = plan.dig('output', 'directory') + end + + if plan.dig('output', 'archive') + @archive_filename = plan.dig('output', 'archive') + end + + @build_name = plan['build_name'] if plan['build_name'] end def tarballs_dir @@ -131,8 +142,8 @@ class Build @sources_dir ||= File.join(root_dir, 'sources') end - def builds_dir - @builds_dir ||= File.join(root_dir, 'builds') + def output_dir + @output_dir ||= (options[:output] || File.join(root_dir, 'builds')) end def brew_dir @@ -363,6 +374,33 @@ class Build emacs_app end + def create_build_dir(app) + app_name = File.basename(app) + target_dir = File.join(output_dir, build_name) + + if File.exist?(target_dir) + err "Output directory #{target_dir} already exists, " \ + 'please delete it and try again' + end + + info "Copying \"#{app_name}\" to: #{target_dir}" + + FileUtils.mkdir_p(target_dir) + FileUtils.cp_r(app, target_dir) + + options[:dist_include]&.each do |filename| + src = File.join(source_dir, filename) + if File.exist?(src) + info "Copying \"#{filename}\" to: #{target_dir}" + FileUtils.cp_r(src, target_dir) + else + info "Warning: #{filename} does not exist in #{source_dir}" + end + end + + [target_dir, File.join(target_dir, File.basename(app))] + end + def symlink_internals(app) return unless options[:native_comp] @@ -397,39 +435,47 @@ class Build FileUtils.chmod('+w', target) end - def archive_filename - return @archive_filename if @archive_filename + def build_name + return @build_name if @build_name + return @build_name = options[:build_name] if options[:build_name] metadata = [ - meta[:ref]&.gsub(/\W/, '-'), meta[:date]&.strftime('%Y-%m-%d'), meta[:sha][0..6], + meta[:ref], "macOS-#{OS.version}", OS.arch - ].compact + ].compact.map { |v| v.gsub(/[^\w_-]+/, '-') } - filename = "Emacs.app-[#{metadata.join('][')}].tbz" - @archive_filename = File.join(builds_dir, filename) + @build_name = "Emacs.#{metadata.join('.')}" end - def archive_app(app) + def archive_filename + @archive_filename ||= File.join(output_dir, "#{build_name}.tbz") + end + + def archive_build(build_dir) filename = File.basename(archive_filename) target_dir = File.dirname(archive_filename) - relative_target_dir = target_dir.gsub(root_dir + '/', '') FileUtils.mkdir_p(target_dir) - app_base = File.basename(app) - app_dir = File.dirname(app) + build = File.basename(build_dir) + parent_dir = File.dirname(build_dir) if !File.exist?(archive_filename) - info "Creating #{filename} archive in \"#{relative_target_dir}\"..." - FileUtils.cd(app_dir) do - system('tar', '-cjf', archive_filename, app_base) + info "Creating #{filename} archive in \"#{target_dir}\"..." + FileUtils.cd(parent_dir) do + system('tar', '-cjf', archive_filename, build) + + if options[:archive_keep] == false + info "Removeing \"#{build}\" directory from #{parent_dir}" + FileUtils.rm_rf(build_dir) + end end else info "#{filename} archive exists in " \ - "#{relative_target_dir}, skipping archving." + "#{target_dir}, skipping archving." end end @@ -908,7 +954,10 @@ if __FILE__ == $PROGRAM_NAME parallel: Etc.nprocessors, rsvg: true, xwidgets: true, - github_auth: true + github_auth: true, + dist_include: ['COPYING'], + archive: true, + archive_keep: false } begin @@ -986,6 +1035,33 @@ if __FILE__ == $PROGRAM_NAME cli_options[:work_dir] = v end + opts.on('-o DIR', '--output DIR', + 'Output directory for finished builds ' \ + '(default: /builds)') do |v| + cli_options[:output] = v + end + + opts.on('--build-name NAME', 'Override generated build name') do |v| + cli_options[:build_name] = v + end + + opts.on('--dist-include x,y,z', + 'List of extra files to copy from Emacs source into build ' \ + 'folder/archive (default: COPYING)') do |v| + cli_options[:dist_include] = v + end + + opts.on('--[no-]archive', + 'Enable/disable creating *.tbz archive (default: enabled)') do |v| + cli_options[:archive] = v + end + + opts.on('--[no-]archive-keep-build-dir', + 'Enable/disable keeping source folder for archive ' \ + '(default: disabled)') do |v| + cli_options[:archive_keep] = v + end + opts.on( '--plan FILE', 'Follow given plan file, instead of using given git ref/sha' From 8d87c01db79201182fbcd1a210b1b19df9209aeb Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sun, 23 May 2021 18:27:13 +0100 Subject: [PATCH 02/10] feat(cli): add basis for new "emacs-builder" CLI tool written in Go This will eventually replace the build-emacs-for-macos script that's written in Ruby. The migration of functionality will happen bit by bit over time. --- .github/workflows/ci.yml | 52 ++++++++++++ .gitignore | 2 + .golangci.yml | 86 ++++++++++++++++++++ Makefile | 163 ++++++++++++++++++++++++++++++++++++++ cmd/emacs-builder/main.go | 24 ++++++ go.mod | 15 ++++ go.sum | 43 ++++++++++ pkg/cli/cli.go | 89 +++++++++++++++++++++ pkg/cli/options.go | 49 ++++++++++++ 9 files changed, 523 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .golangci.yml create mode 100644 cmd/emacs-builder/main.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 pkg/cli/cli.go create mode 100644 pkg/cli/options.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c349108 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +--- +name: CI +on: [push] + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: v1.40 + env: + VERBOSE: "true" + + tidy: + name: Tidy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: 1.16 + - uses: actions/cache@v2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Check if mods are tidy + run: make check-tidy + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: 1.16 + - uses: actions/cache@v2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Run tests + run: make test + env: + VERBOSE: "true" diff --git a/.gitignore b/.gitignore index f75fd16..1c59c21 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ .DS_Store +.envrc Formula/* Gemfile.lock +bin builds sources tarballs diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..34fe368 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,86 @@ +linters-settings: + funlen: + lines: 100 + statements: 150 + goconst: + min-occurrences: 5 + gocyclo: + min-complexity: 20 + govet: + check-shadowing: true + enable-all: true + disable: + - fieldalignment + lll: + line-length: 80 + tab-width: 4 + maligned: + suggest-new: true + misspell: + locale: US + +linters: + disable-all: true + enable: + - bodyclose + - deadcode + - depguard + - dupl + - errcheck + - exportloopref + - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - gofumpt + - goimports + - goprintffuncname + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - nlreturn + - noctx + - nolintlint + - revive + - sqlclosecheck + - staticcheck + - structcheck + - typecheck + - unconvert + - unused + - varcheck + - whitespace + +issues: + include: + # - EXC0002 # disable excluding of issues about comments from golint + exclude: + - Using the variable on range scope `tt` in function literal + - Using the variable on range scope `tc` in function literal + exclude-rules: + - path: "_test\\.go" + linters: + - funlen + - dupl + - goconst + - source: "^//go:generate " + linters: + - lll + - source: "`json:" + linters: + - lll + +run: + skip-dirs: + - builds + - sources + - tarballs + timeout: 2m + allow-parallel-runners: true + modules-download-mode: readonly diff --git a/Makefile b/Makefile index fe08d61..9d47da3 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,166 @@ +SOURCES := $(shell \ + find * \ + -not -path 'sources/*' \ + -not -path 'builds/*' \( \ + -name "*.go" -or \ + -name "go.mod" -or \ + -name "go.sum" -or \ + -name "Makefile" -or \ + -type f -path 'internal/*' -or \ + -type f -path 'cmd/*' -or \ + -type f -path 'pkg/*' \ + \) | grep -v '.DS_Store' \ +) + +# +# Environment +# + +# Verbose output +ifdef VERBOSE +V = -v +endif + +BINDIR := bin +TOOLDIR := $(BINDIR)/tools + +# Global environment variables for all targets +SHELL ?= /bin/bash +SHELL := env \ + GO111MODULE=on \ + GOBIN=$(CURDIR)/$(BINDIR) \ + CGO_ENABLED=0 \ + PATH='$(CURDIR)/$(BINDIR):$(CURDIR)/$(TOOLDIR):$(PATH)' \ + $(SHELL) + +# +# Defaults +# + +# Default target +.DEFAULT_GOAL := build + +# +# Tools +# + +# external tool +define tool # 1: binary-name, 2: go-import-path +TOOLS += $(TOOLDIR)/$(1) + +$(TOOLDIR)/$(1): Makefile + GOBIN="$(CURDIR)/$(TOOLDIR)" go install "$(2)" +endef + +$(eval $(call tool,gofumpt,mvdan.cc/gofumpt@latest)) +$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.40)) +$(eval $(call tool,gomod,github.com/Helcaraxan/gomod@latest)) + +.PHONY: tools +tools: $(TOOLS) + +# +# Build +# + +LDFLAGS := -w -s + +VERSION ?= $(shell git describe --tags --exact 2>/dev/null) +COMMIT ?= $(shell git rev-parse HEAD 2>/dev/null) +DATE ?= $(shell date '+%FT%T%z') + +ifeq ($(VERSION),) + VERSION = 0.0.0-dev +endif + +CMDDIR := cmd +BINS := $(shell test -d "$(CMDDIR)" && cd "$(CMDDIR)" && \ + find * -maxdepth 0 -type d -exec echo $(BINDIR)/{} \;) + +.PHONY: build +build: $(BINS) + +$(BINS): $(BINDIR)/%: $(SOURCES) + mkdir -p "$(BINDIR)" + cd "$(CMDDIR)/$*" && go build -a $(V) \ + -o "$(CURDIR)/$(BINDIR)/$*" \ + -ldflags "$(LDFLAGS) \ + -X main.version=$(VERSION) \ + -X main.commit=$(COMMIT) \ + -X main.date=$(DATE)" + +# +# Development +# + +TEST ?= $$(go list ./... | grep -v 'sources/') + +.PHONY: clean +clean: + rm -rf $(BINARY) $(TOOLS) + rm -f ./go.mod.tidy-check ./go.sum.tidy-check + +.PHONY: test +test: + CGO_ENABLED=1 go test $(V) -count=1 -race $(TESTARGS) $(TEST) + +.PHONY: lint +lint: $(TOOLDIR)/golangci-lint + golangci-lint $(V) run + +.PHONY: format +format: $(TOOLDIR)/gofumpt + gofumpt -w . + +# +# Dependencies +# + +.PHONY: deps +deps: + $(info Downloading dependencies) + go mod download + +.PHONY: deps-update +deps-update: + $(info Downloading dependencies) + go get -u -t ./... + +.PHONY: deps-analyze +deps-analyze: $(TOOLDIR)/gomod + gomod analyze + +.PHONY: tidy +tidy: + go mod tidy $(V) + +.PHONY: verify +verify: + go mod verify + +.SILENT: check-tidy +.PHONY: check-tidy +check-tidy: + cp go.mod go.mod.tidy-check + cp go.sum go.sum.tidy-check + go mod tidy + ( \ + diff go.mod go.mod.tidy-check && \ + diff go.sum go.sum.tidy-check && \ + rm -f go.mod go.sum && \ + mv go.mod.tidy-check go.mod && \ + mv go.sum.tidy-check go.sum \ + ) || ( \ + rm -f go.mod go.sum && \ + mv go.mod.tidy-check go.mod && \ + mv go.sum.tidy-check go.sum; \ + exit 1 \ + ) + +# +# Release +# + .PHONY: new-version new-version: check-npx npx standard-version diff --git a/cmd/emacs-builder/main.go b/cmd/emacs-builder/main.go new file mode 100644 index 0000000..a57fac5 --- /dev/null +++ b/cmd/emacs-builder/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "os" + + "github.com/jimeh/build-emacs-for-macos/pkg/cli" +) + +var ( + version string + commit string + date string +) + +func main() { + cliInstance := cli.New(version, commit, date) + + err := cliInstance.Run(os.Args) + if err != nil { + fmt.Fprintf(os.Stderr, "ERROR: %s\n", err.Error()) + os.Exit(1) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ca9c46e --- /dev/null +++ b/go.mod @@ -0,0 +1,15 @@ +module github.com/jimeh/build-emacs-for-macos + +go 1.16 + +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/fatih/color v1.12.0 // indirect + github.com/hashicorp/go-hclog v0.16.1 + github.com/mattn/go-isatty v0.0.13 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/stretchr/testify v1.6.1 // indirect + github.com/urfave/cli/v2 v2.3.0 + golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..69ca4ad --- /dev/null +++ b/go.sum @@ -0,0 +1,43 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o= +github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go new file mode 100644 index 0000000..224c2a3 --- /dev/null +++ b/pkg/cli/cli.go @@ -0,0 +1,89 @@ +package cli + +import ( + "fmt" + "strings" + + cli2 "github.com/urfave/cli/v2" +) + +type CLI struct { + App *cli2.App + Version string + Commit string + Date string +} + +func New(version, commit, date string) *CLI { + if version == "" { + version = "0.0.0-dev" + } + + c := &CLI{ + Version: version, + Commit: commit, + Date: date, + App: &cli2.App{ + Name: "emacs-builder", + Usage: "Tool to build emacs", + Version: version, + EnableBashCompletion: true, + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "log-level", + Usage: "set log level", + Aliases: []string{"l"}, + Value: "info", + }, + &cli2.BoolFlag{ + Name: "quiet", + Usage: "silence noisy output", + Aliases: []string{"q"}, + Value: false, + }, + cli2.VersionFlag, + }, + Commands: []*cli2.Command{ + { + Name: "version", + Usage: "print the version", + Aliases: []string{"v"}, + Action: func(c *cli2.Context) error { + cli2.VersionPrinter(c) + + return nil + }, + }, + }, + }, + } + + cli2.VersionPrinter = c.VersionPrinter + + return c +} + +func (s *CLI) VersionPrinter(c *cli2.Context) { + version := c.App.Version + if version == "" { + version = "0.0.0-dev" + } + + extra := []string{} + if len(s.Commit) >= 7 { + extra = append(extra, s.Commit[0:7]) + } + if s.Date != "" { + extra = append(extra, s.Date) + } + var extraOut string + if len(extra) > 0 { + extraOut += " (" + strings.Join(extra, ", ") + ")" + } + + fmt.Printf("%s%s\n", version, extraOut) +} + +func (s *CLI) Run(args []string) error { + return s.App.Run(args) +} diff --git a/pkg/cli/options.go b/pkg/cli/options.go new file mode 100644 index 0000000..688bb1a --- /dev/null +++ b/pkg/cli/options.go @@ -0,0 +1,49 @@ +package cli + +import ( + "fmt" + "os" + "sync" + "time" + + "github.com/hashicorp/go-hclog" + cli2 "github.com/urfave/cli/v2" +) + +type Options struct { + quiet bool +} + +func actionWrapper( + f func(*cli2.Context, *Options) error, +) func(*cli2.Context) error { + return func(c *cli2.Context) error { + opts := &Options{ + quiet: c.Bool("quiet"), + } + + levelStr := c.String("log-level") + level := hclog.LevelFromString(levelStr) + if level == hclog.NoLevel { + return fmt.Errorf("invalid log level \"%s\"", levelStr) + } + + // Prevent things from logging if they weren't explicitly given a + // logger. + hclog.SetDefault(hclog.NewNullLogger()) + + // Create custom logger. + logr := hclog.New(&hclog.LoggerOptions{ + Level: level, + Output: os.Stderr, + Mutex: &sync.Mutex{}, + TimeFormat: time.RFC3339, + Color: hclog.ColorOff, + }) + + ctx := hclog.WithContext(c.Context, logr) + c.Context = ctx + + return f(c, opts) + } +} From 1ffd735c23e375479ea6bb2c771553ce4cac902b Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Tue, 8 Jun 2021 00:26:50 +0100 Subject: [PATCH 03/10] feat(plan): add plan command to create build plans --- build-emacs-for-macos | 12 +- go.mod | 11 +- go.sum | 385 ++++++++++++++++++++++++++++++++++- pkg/cli/cli.go | 1 + pkg/cli/plan.go | 128 ++++++++++++ pkg/commit/commit.go | 42 ++++ pkg/gh/gh.go | 24 +++ pkg/osinfo/osinfo.go | 40 ++++ pkg/plan/create.go | 125 ++++++++++++ pkg/plan/plan.go | 82 ++++++++ pkg/repository/repository.go | 91 +++++++++ 11 files changed, 933 insertions(+), 8 deletions(-) create mode 100644 pkg/cli/plan.go create mode 100644 pkg/commit/commit.go create mode 100644 pkg/gh/gh.go create mode 100644 pkg/osinfo/osinfo.go create mode 100644 pkg/plan/create.go create mode 100644 pkg/plan/plan.go create mode 100644 pkg/repository/repository.go diff --git a/build-emacs-for-macos b/build-emacs-for-macos index d8b970f..241e688 100755 --- a/build-emacs-for-macos +++ b/build-emacs-for-macos @@ -118,9 +118,9 @@ class Build plan = YAML.safe_load(File.read(filename), [:Time]) @meta = { - sha: plan.dig('commit', 'sha'), - ref: plan.dig('commit', 'ref'), - date: plan.dig('commit', 'date') + sha: plan.dig('source', 'commit', 'sha'), + ref: plan.dig('source', 'ref'), + date: plan.dig('source', 'commit', 'date') } if plan.dig('output', 'directory') @@ -131,7 +131,11 @@ class Build @archive_filename = plan.dig('output', 'archive') end - @build_name = plan['build_name'] if plan['build_name'] + if plan.dig('output', 'disk_image') || !plan.dig('output', 'archive') + options[:archive] = false + end + + @build_name = plan.dig('build', 'name') if plan.dig('build', 'name') end def tarballs_dir diff --git a/go.mod b/go.mod index ca9c46e..792ccbd 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,18 @@ go 1.16 require ( github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/fatih/color v1.12.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-github/v35 v35.3.0 + github.com/google/go-querystring v1.1.0 // indirect github.com/hashicorp/go-hclog v0.16.1 github.com/mattn/go-isatty v0.0.13 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stretchr/testify v1.6.1 // indirect github.com/urfave/cli/v2 v2.3.0 - golang.org/x/sys v0.0.0-20210603125802-9665404d3644 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect + golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect + golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1 + golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect + google.golang.org/appengine v1.6.7 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) diff --git a/go.sum b/go.sum index 69ca4ad..a22249a 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,130 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github/v35 v35.3.0 h1:fU+WBzuukn0VssbayTT+Zo3/ESKX9JYWjbZTLOTEyho= +github.com/google/go-github/v35 v35.3.0/go.mod h1:yWB7uCcVWaUbUP74Aq3whuMySRMatyRmq5U9FTNlbio= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o= github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -20,24 +135,290 @@ github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1y github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/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-20191209160850-c0dbc17a3553/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-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1 h1:x622Z2o4hgCr/4CiKWc51jHVKaWdtVpBNmEI8wI9Qns= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +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= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 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= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 224c2a3..befee09 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -44,6 +44,7 @@ func New(version, commit, date string) *CLI { cli2.VersionFlag, }, Commands: []*cli2.Command{ + planCmd(), { Name: "version", Usage: "print the version", diff --git a/pkg/cli/plan.go b/pkg/cli/plan.go new file mode 100644 index 0000000..7c3cfd8 --- /dev/null +++ b/pkg/cli/plan.go @@ -0,0 +1,128 @@ +package cli + +import ( + "os" + "path/filepath" + + "github.com/hashicorp/go-hclog" + "github.com/jimeh/build-emacs-for-macos/pkg/plan" + cli2 "github.com/urfave/cli/v2" +) + +func planCmd() *cli2.Command { + wd, err := os.Getwd() + if err != nil { + wd = "" + } + + tokenDefaultText := "" + if len(os.Getenv("GITHUB_TOKEN")) > 0 { + tokenDefaultText = "***" + } + + return &cli2.Command{ + Name: "plan", + Usage: "plan a Emacs.app bundle with codeplan", + ArgsUsage: "", + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "emacs-repo", + Usage: "GitHub repository to get Emacs commit info and " + + "tarball from", + Aliases: []string{"e"}, + EnvVars: []string{"EMACS_REPO"}, + Value: "emacs-mirror/emacs", + }, + &cli2.StringFlag{ + Name: "sha", + Usage: "override commit SHA of specified git branch/tag", + }, + &cli2.StringFlag{ + Name: "output", + Usage: "output filename to write plan to instead of printing " + + "to STDOUT", + Aliases: []string{"o"}, + }, + &cli2.StringFlag{ + Name: "output-dir", + Usage: "output directory where build result is stored", + Value: filepath.Join(wd, "builds"), + }, + &cli2.StringFlag{ + Name: "test-build", + Usage: "plan a test build with given name, which is " + + "published to a draft or pre-release " + + "\"test-builds\" release", + }, + &cli2.StringFlag{ + Name: "test-release-type", + Value: "prerelease", + Usage: "type of release when doing a test-build " + + "(prerelease or draft)", + }, + &cli2.StringFlag{ + Name: "github-token", + Usage: "GitHub API Token", + EnvVars: []string{"GITHUB_TOKEN"}, + DefaultText: tokenDefaultText, + }, + }, + Action: actionWrapper(planAction), + } +} + +func planAction(c *cli2.Context, opts *Options) error { + logger := hclog.FromContext(c.Context).Named("plan") + + ref := c.Args().Get(0) + if ref == "" { + ref = "master" + } + + planOpts := &plan.Options{ + EmacsRepo: c.String("emacs-repo"), + Ref: ref, + SHAOverride: c.String("sha"), + OutputDir: c.String("output-dir"), + TestBuild: c.String("test-build"), + TestBuildType: plan.Prerelease, + GithubToken: c.String("github-token"), + } + + if c.String("test-build-type") == "draft" { + planOpts.TestBuildType = plan.Draft + } + + if !opts.quiet { + planOpts.Output = os.Stdout + } + + p, err := plan.Create(c.Context, planOpts) + if err != nil { + return err + } + + planYAML, err := p.YAML() + if err != nil { + return err + } + + var out *os.File + out = os.Stdout + if f := c.String("output"); f != "" { + logger.Info("writing plan", "file", f) + logger.Debug("content", "yaml", planYAML) + out, err = os.Create(f) + if err != nil { + return err + } + defer out.Close() + } + + _, err = out.WriteString(planYAML) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/commit/commit.go b/pkg/commit/commit.go new file mode 100644 index 0000000..f7d4b79 --- /dev/null +++ b/pkg/commit/commit.go @@ -0,0 +1,42 @@ +package commit + +import ( + "fmt" + "time" + + "github.com/google/go-github/v35/github" +) + +type Commit struct { + SHA string `yaml:"sha"` + Date *time.Time `yaml:"date"` + Author string `yaml:"author"` + Committer string `yaml:"committer"` + Message string `yaml:"message"` +} + +func New(rc *github.RepositoryCommit) *Commit { + return &Commit{ + SHA: rc.GetSHA(), + Date: rc.GetCommit().GetCommitter().Date, + Author: fmt.Sprintf( + "%s <%s>", + rc.GetCommit().GetAuthor().GetName(), + rc.GetCommit().GetAuthor().GetEmail(), + ), + Committer: fmt.Sprintf( + "%s <%s>", + rc.GetCommit().GetCommitter().GetName(), + rc.GetCommit().GetCommitter().GetEmail(), + ), + Message: rc.GetCommit().GetMessage(), + } +} + +func (s *Commit) ShortSHA() string { + return s.SHA[0:7] +} + +func (s *Commit) DateString() string { + return s.Date.Format("2006-01-02") +} diff --git a/pkg/gh/gh.go b/pkg/gh/gh.go new file mode 100644 index 0000000..f614819 --- /dev/null +++ b/pkg/gh/gh.go @@ -0,0 +1,24 @@ +package gh + +import ( + "context" + "os" + + "github.com/google/go-github/v35/github" + "golang.org/x/oauth2" +) + +func New(ctx context.Context, token string) *github.Client { + if token == "" { + token = os.Getenv("GITHUB_TOKEN") + } + + if token == "" { + return github.NewClient(nil) + } + + ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) + tc := oauth2.NewClient(ctx, ts) + + return github.NewClient(tc) +} diff --git a/pkg/osinfo/osinfo.go b/pkg/osinfo/osinfo.go new file mode 100644 index 0000000..e8bca96 --- /dev/null +++ b/pkg/osinfo/osinfo.go @@ -0,0 +1,40 @@ +package osinfo + +import ( + "os/exec" + "strings" +) + +type OSInfo struct { + Name string `yaml:"name"` + Version string `yaml:"version"` + Arch string `yaml:"arch"` +} + +func New() (*OSInfo, error) { + version, err := exec.Command("sw_vers", "-productVersion").CombinedOutput() + if err != nil { + return nil, err + } + + arch, err := exec.Command("uname", "-m").CombinedOutput() + if err != nil { + return nil, err + } + + return &OSInfo{ + Name: "macOS", + Version: strings.TrimSpace(string(version)), + Arch: strings.TrimSpace(string(arch)), + }, nil +} + +func (s *OSInfo) MajorMinor() string { + parts := strings.Split(s.Version, ".") + max := len(parts) + if max > 2 { + max = 2 + } + + return strings.Join(parts[0:max], ".") +} diff --git a/pkg/plan/create.go b/pkg/plan/create.go new file mode 100644 index 0000000..fc0eecc --- /dev/null +++ b/pkg/plan/create.go @@ -0,0 +1,125 @@ +package plan + +import ( + "context" + "fmt" + "io" + "regexp" + "strings" + + "github.com/hashicorp/go-hclog" + "github.com/jimeh/build-emacs-for-macos/pkg/commit" + "github.com/jimeh/build-emacs-for-macos/pkg/gh" + "github.com/jimeh/build-emacs-for-macos/pkg/osinfo" + "github.com/jimeh/build-emacs-for-macos/pkg/repository" +) + +var nonAlphaNum = regexp.MustCompile(`[^\w_-]+`) + +type TestBuildType string + +//nolint:golint +const ( + Draft TestBuildType = "draft" + Prerelease TestBuildType = "prerelease" +) + +type Options struct { + GithubToken string + EmacsRepo string + Ref string + SHAOverride string + OutputDir string + TestBuild string + TestBuildType TestBuildType + Output io.Writer +} + +func Create(ctx context.Context, opts *Options) (*Plan, error) { + logger := hclog.FromContext(ctx).Named("plan") + + repo, err := repository.NewGitHub(opts.EmacsRepo) + if err != nil { + return nil, err + } + + gh := gh.New(ctx, opts.GithubToken) + + lookupRef := opts.Ref + if opts.SHAOverride != "" { + lookupRef = opts.SHAOverride + } + logger.Info("fetching commit info", "ref", lookupRef) + + repoCommit, _, err := gh.Repositories.GetCommit( + ctx, repo.Owner(), repo.Name(), lookupRef, + ) + if err != nil { + return nil, err + } + + commitInfo := commit.New(repoCommit) + osInfo, err := osinfo.New() + if err != nil { + return nil, err + } + + releaseName := fmt.Sprintf( + "Emacs.%s.%s.%s", + commitInfo.DateString(), + commitInfo.ShortSHA(), + sanitizeString(opts.Ref), + ) + buildName := fmt.Sprintf( + "%s.%s.%s", + releaseName, + sanitizeString(osInfo.Name+"-"+osInfo.MajorMinor()), + sanitizeString(osInfo.Arch), + ) + diskImage := buildName + ".dmg" + + plan := &Plan{ + Build: &Build{ + Name: buildName, + }, + Source: &Source{ + Ref: opts.Ref, + Repository: repo, + Commit: commitInfo, + Tarball: &Tarball{ + URL: repo.TarballURL(commitInfo.SHA), + }, + }, + OS: osInfo, + Release: &Release{ + Name: releaseName, + }, + Output: &Output{ + Directory: opts.OutputDir, + DiskImage: diskImage, + }, + } + + if opts.TestBuild != "" { + testName := sanitizeString(opts.TestBuild) + + plan.Build.Name += ".test." + testName + plan.Release.Title = "Test Builds" + plan.Release.Name = "test-builds" + if opts.TestBuildType == Draft { + plan.Release.Draft = true + } else { + plan.Release.Prerelease = true + } + + index := strings.LastIndex(diskImage, ".") + plan.Output.DiskImage = diskImage[:index] + ".test." + + testName + diskImage[index:] + } + + return plan, nil +} + +func sanitizeString(s string) string { + return nonAlphaNum.ReplaceAllString(s, "-") +} diff --git a/pkg/plan/plan.go b/pkg/plan/plan.go new file mode 100644 index 0000000..e33181a --- /dev/null +++ b/pkg/plan/plan.go @@ -0,0 +1,82 @@ +package plan + +import ( + "bytes" + "io" + "os" + + "github.com/jimeh/build-emacs-for-macos/pkg/commit" + "github.com/jimeh/build-emacs-for-macos/pkg/osinfo" + "github.com/jimeh/build-emacs-for-macos/pkg/repository" + "gopkg.in/yaml.v3" +) + +type Plan struct { + Build *Build `yaml:"build,omitempty"` + Source *Source `yaml:"source,omitempty"` + OS *osinfo.OSInfo `yaml:"os,omitempty"` + Release *Release `yaml:"release,omitempty"` + Output *Output `yaml:"output,omitempty"` +} + +// Load attempts to loads a plan YAML from given filename. +func Load(filename string) (*Plan, error) { + b, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + + p := &Plan{} + err = yaml.Unmarshal(b, p) + if err != nil { + return nil, err + } + + return p, nil +} + +// WriteYAML writes plan in YAML format to given io.Writer. +func (s *Plan) WriteYAML(w io.Writer) error { + enc := yaml.NewEncoder(w) + enc.SetIndent(2) + + return enc.Encode(s) +} + +// YAML returns plan in YAML format. +func (s *Plan) YAML() (string, error) { + var buf bytes.Buffer + err := s.WriteYAML(&buf) + if err != nil { + return "", err + } + + return buf.String(), nil +} + +type Build struct { + Name string `yaml:"name,omitempty"` +} + +type Source struct { + Ref string `yaml:"ref,omitempty"` + Repository *repository.Repository `yaml:"repository,omitempty"` + Commit *commit.Commit `yaml:"commit,omitempty"` + Tarball *Tarball `yaml:"tarball,omitempty"` +} + +type Tarball struct { + URL string `yaml:"url,omitempty"` +} + +type Release struct { + Name string `yaml:"name"` + Title string `yaml:"title,omitempty"` + Draft bool `yaml:"draft,omitempty"` + Prerelease bool `yaml:"prerelease,omitempty"` +} + +type Output struct { + Directory string `yaml:"directory,omitempty"` + DiskImage string `yaml:"disk_image,omitempty"` +} diff --git a/pkg/repository/repository.go b/pkg/repository/repository.go new file mode 100644 index 0000000..98d5eeb --- /dev/null +++ b/pkg/repository/repository.go @@ -0,0 +1,91 @@ +package repository + +import ( + "errors" + "fmt" + "strings" +) + +//nolint:golint +var ( + Err = errors.New("repository") + ErrGitHub = fmt.Errorf("%w: github", Err) +) + +const GitHubBaseURL = "https://github.com/" + +// Type is a repository type +type Type string + +const GitHub Type = "github" + +// Repository represents basic information about a repository with helper +// methods to get various pieces of information from it. +type Repository struct { + Type Type `yaml:"type,omitempty"` + Source string `yaml:"source,omitempty"` +} + +func NewGitHub(ownerAndName string) (*Repository, error) { + parts := strings.Split(ownerAndName, "/") + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return nil, fmt.Errorf( + "%w: repository must be give in \"owner/name\" format", + ErrGitHub, + ) + } + + return &Repository{ + Type: GitHub, + Source: ownerAndName, + }, nil +} + +func (s *Repository) Owner() string { + switch s.Type { + case GitHub: + return strings.SplitN(s.Source, "/", 2)[0] + default: + return "" + } +} + +func (s *Repository) Name() string { + switch s.Type { + case GitHub: + return strings.SplitN(s.Source, "/", 2)[1] + default: + return "" + } +} + +func (s *Repository) URL() string { + switch s.Type { + case GitHub: + return GitHubBaseURL + s.Source + default: + return "" + } +} + +func (s *Repository) CloneURL() string { + switch s.Type { + case GitHub: + return GitHubBaseURL + s.Source + ".git" + default: + return "" + } +} + +func (s *Repository) TarballURL(ref string) string { + if ref == "" { + return "" + } + + switch s.Type { + case GitHub: + return GitHubBaseURL + s.Source + "/tarball/" + ref + default: + return "" + } +} From 698756ac5597d3dc7b69f28bc209093fc8c11f30 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sun, 23 May 2021 18:30:10 +0100 Subject: [PATCH 04/10] feat(sign): add sign command to sign Emacs.app bundles with codesign The sign command signs Emacs.app application bundles with Apple's codesign utility. It does a few things outside of just executing codesign: - Is aware of *.eln native-compilation files, which need to be explicitly searched for on disk and passed to codesign, as they are not detected when using the "--deep" option. - Is aware of Contents/MacOS/bin/emacs CLI helper tool which we add into the application bundle, and specifically passed it to codesign as well. - By default provides a set of entitlements which are relevant for Emacs when running codesign. --- go.mod | 3 +- go.sum | 7 +- pkg/cli/cli.go | 1 + pkg/cli/sign.go | 114 ++++++++++++++++++++++++ pkg/sign/emacs.go | 159 ++++++++++++++++++++++++++++++++++ pkg/sign/entitlements.go | 54 ++++++++++++ pkg/sign/entitlements.tpl | 9 ++ pkg/sign/entitlements_test.go | 117 +++++++++++++++++++++++++ pkg/sign/files.go | 67 ++++++++++++++ pkg/sign/options.go | 16 ++++ 10 files changed, 545 insertions(+), 2 deletions(-) create mode 100644 pkg/cli/sign.go create mode 100644 pkg/sign/emacs.go create mode 100644 pkg/sign/entitlements.go create mode 100644 pkg/sign/entitlements.tpl create mode 100644 pkg/sign/entitlements_test.go create mode 100644 pkg/sign/files.go create mode 100644 pkg/sign/options.go diff --git a/go.mod b/go.mod index 792ccbd..bf739af 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,10 @@ require ( github.com/google/go-github/v35 v35.3.0 github.com/google/go-querystring v1.1.0 // indirect github.com/hashicorp/go-hclog v0.16.1 + github.com/jimeh/undent v1.1.0 github.com/mattn/go-isatty v0.0.13 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/stretchr/testify v1.6.1 // indirect + github.com/stretchr/testify v1.7.0 github.com/urfave/cli/v2 v2.3.0 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e // indirect golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect diff --git a/go.sum b/go.sum index a22249a..66a4802 100644 --- a/go.sum +++ b/go.sum @@ -117,6 +117,8 @@ github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jimeh/undent v1.1.0 h1:Cge7P4Ws6buy0SVuHBluY/aOKdFuJUMzoJswfAHZ4zE= +github.com/jimeh/undent v1.1.0/go.mod h1:oxYCIzdbyQNy8GXnCnjRJ2NS6Uq4p4yWoeawiGFqoHI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -136,6 +138,8 @@ github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rhysd/go-fakeio v1.0.0 h1:+TjiKCOs32dONY7DaoVz/VPOdvRkPfBkEyUDIpM8FQY= +github.com/rhysd/go-fakeio v1.0.0/go.mod h1:joYxF906trVwp2JLrE4jlN7A0z6wrz8O6o1UjarbFzE= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -144,8 +148,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index befee09..c0b84e3 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -45,6 +45,7 @@ func New(version, commit, date string) *CLI { }, Commands: []*cli2.Command{ planCmd(), + signCmd(), { Name: "version", Usage: "print the version", diff --git a/pkg/cli/sign.go b/pkg/cli/sign.go new file mode 100644 index 0000000..cd54876 --- /dev/null +++ b/pkg/cli/sign.go @@ -0,0 +1,114 @@ +package cli + +import ( + "os" + "path/filepath" + + "github.com/jimeh/build-emacs-for-macos/pkg/plan" + "github.com/jimeh/build-emacs-for-macos/pkg/sign" + cli2 "github.com/urfave/cli/v2" +) + +func signCmd() *cli2.Command { + return &cli2.Command{ + Name: "sign", + Usage: "sign a Emacs.app bundle with codesign", + ArgsUsage: "", + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "sign", + Aliases: []string{"s"}, + Usage: "signing identity passed to codeside", + EnvVars: []string{"AC_SIGN_IDENTITY"}, + Required: true, + }, + &cli2.StringSliceFlag{ + Name: "entitlements", + Aliases: []string{"e"}, + Usage: "comma-separated list of entitlements to enable", + Value: cli2.NewStringSlice(sign.DefaultEmacsEntitlements...), + }, + &cli2.BoolFlag{ + Name: "deep", + Aliases: []string{"d"}, + Usage: "pass --deep to codesign", + Value: true, + }, + &cli2.BoolFlag{ + Name: "timestamp", + Aliases: []string{"t"}, + Usage: "pass --timestamp to codesign", + Value: true, + }, + &cli2.BoolFlag{ + Name: "force", + Aliases: []string{"f"}, + Usage: "pass --force to codesign", + Value: true, + }, + &cli2.BoolFlag{ + Name: "verbose", + Aliases: []string{"v"}, + Usage: "pass --verbose to codesign", + Value: false, + }, + &cli2.StringSliceFlag{ + Name: "options", + Aliases: []string{"o"}, + Usage: "options passed to codesign", + Value: cli2.NewStringSlice("runtime"), + }, + &cli2.StringFlag{ + Name: "codesign", + Usage: "specify custom path to codesign executable", + }, + &cli2.StringFlag{ + Name: "plan", + Usage: "path to build plan YAML file produced by " + + "emacs-builder plan", + Aliases: []string{"p"}, + EnvVars: []string{"EMACS_BUILDER_PLAN"}, + TakesFile: true, + }, + }, + Action: actionWrapper(signAction), + } +} + +func signAction(c *cli2.Context, opts *Options) error { + signOpts := &sign.Options{ + Identity: c.String("sign"), + Options: c.StringSlice("options"), + Deep: c.Bool("deep"), + Timestamp: c.Bool("timestamp"), + Force: c.Bool("force"), + Verbose: c.Bool("verbose"), + CodeSignCmd: c.String("codesign"), + } + + if v := c.StringSlice("entitlements"); len(v) > 0 { + e := sign.Entitlements(v) + signOpts.Entitlements = &e + } + + if !opts.quiet { + signOpts.Output = os.Stdout + } + + app := c.Args().Get(0) + + if f := c.String("plan"); f != "" { + p, err := plan.Load(f) + if err != nil { + return err + } + + if p.Output != nil && p.Build != nil { + app = filepath.Join( + p.Output.Directory, p.Build.Name, "Emacs.app", + ) + } + } + + return sign.Emacs(c.Context, app, signOpts) +} diff --git a/pkg/sign/emacs.go b/pkg/sign/emacs.go new file mode 100644 index 0000000..a5e0398 --- /dev/null +++ b/pkg/sign/emacs.go @@ -0,0 +1,159 @@ +package sign + +import ( + "context" + "fmt" + "io/fs" + "os" + "path/filepath" + "strings" + + "github.com/hashicorp/go-hclog" +) + +// Emacs signs a Emacs.app application bundle with Apple's codesign utility, +// using correct default entitlements, and also pre-signing any *.eln files +// which are in the bundle, as codesign will not detect them as requiring +// signing even with the --deep flag. +func Emacs(ctx context.Context, appBundle string, opts *Options) error { + if !strings.HasSuffix(appBundle, ".app") { + return fmt.Errorf("%s is not a .app application bundle", appBundle) + } + + appBundle, err := filepath.Abs(appBundle) + if err != nil { + return err + } + + _, err = os.Stat(appBundle) + if err != nil { + return err + } + + logger := hclog.FromContext(ctx).Named("sign") + logger.Info("preparing to sign Emacs.app", "app", appBundle) + + newOpts := *opts + + if newOpts.EntitlementsFile == "" { + if newOpts.Entitlements == nil { + e := Entitlements(DefaultEmacsEntitlements) + newOpts.Entitlements = &e + } + + f, err2 := newOpts.Entitlements.TempFile() + if err2 != nil { + return err2 + } + defer os.Remove(f) + + newOpts.EntitlementsFile = f + newOpts.Entitlements = nil + } + + err = signElnFiles(ctx, appBundle, &newOpts) + if err != nil { + return err + } + + err = signCLIHelper(ctx, appBundle, &newOpts) + if err != nil { + return err + } + + // Ensure app bundle is signed last, as modifications to the bundle after + // signing will invalidate the signature. Hence anything within it that + // needs to be separately signed, has to happen before signing the whole + // application bundle. + return Files(ctx, []string{appBundle}, &newOpts) +} + +func signElnFiles(ctx context.Context, appBundle string, opts *Options) error { + logger := hclog.FromContext(ctx).Named("sign") + + elnFiles, err := elnFiles(appBundle) + if err != nil { + return err + } + + if len(elnFiles) == 0 { + return nil + } + + logger.Info(fmt.Sprintf( + "found %d native-lisp *.eln files in %s to sign", + len(elnFiles), filepath.Base(appBundle), + )) + for _, file := range elnFiles { + err := Files(ctx, []string{file}, opts) + if err != nil { + return err + } + } + + return nil +} + +func signCLIHelper(ctx context.Context, appBundle string, opts *Options) error { + logger := hclog.FromContext(ctx).Named("sign") + + cliHelper := filepath.Join(appBundle, "Contents", "MacOS", "bin", "emacs") + fi, err := os.Stat(cliHelper) + if err != nil && !os.IsNotExist(err) { + return err + } else if err == nil && fi.Mode().IsRegular() { + logger.Info(fmt.Sprintf( + "found Contents/MacOS/bin/emacs CLI helper script in %s to sign", + filepath.Base(appBundle), + )) + + err = Files(ctx, []string{cliHelper}, opts) + if err != nil { + return err + } + } + + return nil +} + +// elnFiles finds all native-compilation *.eln files within a Emacs.app bundle, +// based on expected paths they might be stored in. +func elnFiles(emacsApp string) ([]string, error) { + dirs := []string{ + // Current *.eln location. + filepath.Join(emacsApp, "Contents", "Resources", "native-lisp"), + // Legacy *.eln location. + filepath.Join(emacsApp, "Contents", "MacOS", "lib", "emacs"), + } + + var files []string + walkDirFunc := func(path string, _d fs.DirEntry, _err error) error { + if strings.HasSuffix(path, ".eln") { + files = append(files, path) + } + + return nil + } + + for _, dir := range dirs { + fi, err := os.Stat(dir) + if err != nil { + if os.IsNotExist(err) { + continue + } + + return nil, err + } + + if !fi.IsDir() { + continue + } + + err = filepath.WalkDir(dir, walkDirFunc) + if err != nil { + return nil, err + } + } + + return files, nil +} diff --git a/pkg/sign/entitlements.go b/pkg/sign/entitlements.go new file mode 100644 index 0000000..7941d20 --- /dev/null +++ b/pkg/sign/entitlements.go @@ -0,0 +1,54 @@ +package sign + +import ( + "bytes" + _ "embed" + "io" + "os" + "text/template" +) + +// DefaultEmacsEntitlements is the default set of entitlements application +// bundles are signed with if no entitlements are provided. +var DefaultEmacsEntitlements = []string{ + "com.apple.security.cs.allow-jit", + "com.apple.security.network.client", + "com.apple.security.cs.disable-library-validation", + "com.apple.security.automation.apple-events", +} + +//go:embed entitlements.tpl +var entitlementsTemplate string + +type Entitlements []string + +func (e Entitlements) XML() ([]byte, error) { + var buf bytes.Buffer + err := e.Write(&buf) + + return buf.Bytes(), err +} + +func (e Entitlements) Write(w io.Writer) error { + tpl, err := template.New("entitlements.plist").Parse(entitlementsTemplate) + if err != nil { + return err + } + + return tpl.Execute(w, e) +} + +func (e Entitlements) TempFile() (string, error) { + f, err := os.CreateTemp("", "*.entitlements.plist") + if err != nil { + return "", err + } + defer f.Close() + + err = e.Write(f) + if err != nil { + return "", err + } + + return f.Name(), nil +} diff --git a/pkg/sign/entitlements.tpl b/pkg/sign/entitlements.tpl new file mode 100644 index 0000000..a0477ef --- /dev/null +++ b/pkg/sign/entitlements.tpl @@ -0,0 +1,9 @@ + + + + + {{- range . }} + {{ . }} + {{ end }} + + diff --git a/pkg/sign/entitlements_test.go b/pkg/sign/entitlements_test.go new file mode 100644 index 0000000..b0d5fae --- /dev/null +++ b/pkg/sign/entitlements_test.go @@ -0,0 +1,117 @@ +package sign + +import ( + "bytes" + "os" + "strings" + "testing" + + "github.com/jimeh/undent" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var entitlementsTestCases = []struct { + name string + entitlements Entitlements + want string +}{ + { + name: "none", + entitlements: Entitlements{}, + //nolint:lll + want: undent.String(` + + + + + + `, + ), + }, + { + name: "one", + entitlements: Entitlements{"com.apple.security.cs.allow-jit"}, + //nolint:lll + want: undent.String(` + + + + + com.apple.security.cs.allow-jit + + + `, + ), + }, + { + name: "many", + entitlements: Entitlements{ + "com.apple.security.cs.allow-jit", + "com.apple.security.network.client", + "com.apple.security.cs.disable-library-validation", + "com.apple.security.automation.apple-events", + }, + //nolint:lll + want: undent.String(` + + + + + com.apple.security.cs.allow-jit + + com.apple.security.network.client + + com.apple.security.cs.disable-library-validation + + com.apple.security.automation.apple-events + + + `, + ), + }, +} + +func TestDefaultEmacsEntitlements(t *testing.T) { + assert.Equal(t, + []string{ + "com.apple.security.cs.allow-jit", + "com.apple.security.network.client", + "com.apple.security.cs.disable-library-validation", + "com.apple.security.automation.apple-events", + }, + DefaultEmacsEntitlements, + ) +} + +func TestEntitlements_Write(t *testing.T) { + for _, tt := range entitlementsTestCases { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + + err := tt.entitlements.Write(&buf) + require.NoError(t, err) + + assert.Equal(t, tt.want, strings.TrimSpace(buf.String())) + }) + } +} + +func TestEntitlements_TempFile(t *testing.T) { + for _, tt := range entitlementsTestCases { + t.Run(tt.name, func(t *testing.T) { + tmpFile, err := tt.entitlements.TempFile() + require.NoError(t, err) + defer os.Remove(tmpFile) + + content, err := os.ReadFile(tmpFile) + require.NoError(t, err) + + assert.Equal(t, tt.want, strings.TrimSpace(string(content))) + assert.True(t, + strings.HasSuffix(tmpFile, ".entitlements.plist"), + "temp file name does not match \"*.entitlements.plist\"", + ) + }) + } +} diff --git a/pkg/sign/files.go b/pkg/sign/files.go new file mode 100644 index 0000000..da2ca28 --- /dev/null +++ b/pkg/sign/files.go @@ -0,0 +1,67 @@ +package sign + +import ( + "context" + "os" + "os/exec" + "strings" + + "github.com/hashicorp/go-hclog" +) + +func Files(ctx context.Context, files []string, opts *Options) error { + logger := hclog.FromContext(ctx).Named("sign") + args := []string{} + + if opts.Identity != "" { + args = append(args, "--sign", opts.Identity) + } + if opts.Deep { + args = append(args, "--deep") + } + if opts.Timestamp { + args = append(args, "--timestamp") + } + if opts.Force { + args = append(args, "--force") + } + if opts.Verbose { + args = append(args, "--verbose") + } + if len(opts.Options) > 0 { + args = append(args, "--options", strings.Join(opts.Options, ",")) + } + + if opts.EntitlementsFile != "" { + args = append(args, "--entitlements", opts.EntitlementsFile) + } else if opts.Entitlements != nil { + entitlementsFile, err := opts.Entitlements.TempFile() + if err != nil { + return err + } + defer os.Remove(entitlementsFile) + logger.Debug("wrote entitlements", "file", entitlementsFile) + + args = append(args, "--entitlements", entitlementsFile) + } + + baseCmd := opts.CodeSignCmd + if baseCmd == "" { + path, err := exec.LookPath("codesign") + if err != nil { + return err + } + baseCmd = path + } + + args = append(args, files...) + + logger.Debug("executing", "command", baseCmd, "args", args) + cmd := exec.CommandContext(ctx, baseCmd, args...) + if opts.Output != nil { + cmd.Stdout = opts.Output + cmd.Stderr = opts.Output + } + + return cmd.Run() +} diff --git a/pkg/sign/options.go b/pkg/sign/options.go new file mode 100644 index 0000000..b2d4195 --- /dev/null +++ b/pkg/sign/options.go @@ -0,0 +1,16 @@ +package sign + +import "io" + +type Options struct { + Identity string + Entitlements *Entitlements + EntitlementsFile string + Options []string + Deep bool + Timestamp bool + Force bool + Verbose bool + Output io.Writer + CodeSignCmd string +} From 72d0254772bf7d0937b41634e9a4bfcf87f60fb6 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Mon, 31 May 2021 00:14:11 +0100 Subject: [PATCH 05/10] feat(notarize): add notarize command to notarize and staple *.dmg files --- go.mod | 6 +++ go.sum | 39 ++++++++++++++++ pkg/cli/cli.go | 1 + pkg/cli/notarize.go | 79 ++++++++++++++++++++++++++++++++ pkg/notarize/notarize.go | 98 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 223 insertions(+) create mode 100644 pkg/cli/notarize.go create mode 100644 pkg/notarize/notarize.go diff --git a/go.mod b/go.mod index bf739af..8a6f862 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,14 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-github/v35 v35.3.0 github.com/google/go-querystring v1.1.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v0.16.1 + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.0 // indirect github.com/jimeh/undent v1.1.0 github.com/mattn/go-isatty v0.0.13 // indirect + github.com/mitchellh/gon v0.2.3 github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stretchr/testify v1.7.0 github.com/urfave/cli/v2 v2.3.0 @@ -20,4 +25,5 @@ require ( golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect ) diff --git a/go.sum b/go.sum index 66a4802..9602a2c 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,9 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -55,6 +58,7 @@ github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -66,6 +70,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -112,11 +117,27 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.9.3-0.20191025211905-234833755cb2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o= github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.6.3/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jimeh/undent v1.1.0 h1:Cge7P4Ws6buy0SVuHBluY/aOKdFuJUMzoJswfAHZ4zE= github.com/jimeh/undent v1.1.0/go.mod h1:oxYCIzdbyQNy8GXnCnjRJ2NS6Uq4p4yWoeawiGFqoHI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -127,6 +148,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -135,6 +157,9 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/gon v0.2.3 h1:fObN7hD14VacGG++t27GzTW6opP0lwI7TsgTPL55wBo= +github.com/mitchellh/gon v0.2.3/go.mod h1:Ua18ZhqjZHg8VyqZo8kNHAY331ntV6nNJ9mT3s2mIo8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -144,24 +169,32 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sebdah/goldie v1.0.0 h1:9GNhIat69MSlz/ndaBg48vl9dF5fI+NBB6kfOxgfkMc= +github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -199,6 +232,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -248,6 +282,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -412,6 +447,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -424,6 +460,9 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +howett.net/plist v0.0.0-20201203080718-1454fab16a06 h1:QDxUo/w2COstK1wIBYpzQlHX/NqaQTcf9jyz347nI58= +howett.net/plist v0.0.0-20201203080718-1454fab16a06/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index c0b84e3..b1eeea9 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -46,6 +46,7 @@ func New(version, commit, date string) *CLI { Commands: []*cli2.Command{ planCmd(), signCmd(), + notarizeCmd(), { Name: "version", Usage: "print the version", diff --git a/pkg/cli/notarize.go b/pkg/cli/notarize.go new file mode 100644 index 0000000..f619d92 --- /dev/null +++ b/pkg/cli/notarize.go @@ -0,0 +1,79 @@ +package cli + +import ( + "path/filepath" + + "github.com/jimeh/build-emacs-for-macos/pkg/notarize" + "github.com/jimeh/build-emacs-for-macos/pkg/plan" + cli2 "github.com/urfave/cli/v2" +) + +func notarizeCmd() *cli2.Command { + return &cli2.Command{ + Name: "notarize", + Usage: "notarize and staple a dmg, zip, or pkg", + ArgsUsage: "", + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "bundle-id", + Usage: "Bundle", + Value: "org.gnu.Emacs", + }, + &cli2.StringFlag{ + Name: "ac-username", + Usage: "Apple Connect username", + EnvVars: []string{"AC_USERNAME"}, + }, + &cli2.StringFlag{ + Name: "ac-password", + Usage: "Apple Connect password", + Value: "@env:AC_PASSWORD", + }, + &cli2.StringFlag{ + Name: "ac-provider", + Usage: "Apple Connect provider", + EnvVars: []string{"AC_PROVIDER"}, + }, + &cli2.BoolFlag{ + Name: "staple", + Usage: "stable file after notarization", + Value: true, + }, + &cli2.StringFlag{ + Name: "plan", + Usage: "path to build plan YAML file produced by " + + "emacs-builder plan", + Aliases: []string{"p"}, + EnvVars: []string{"EMACS_BUILDER_PLAN"}, + TakesFile: true, + }, + }, + Action: actionWrapper(notarizeAction), + } +} + +func notarizeAction(c *cli2.Context, opts *Options) error { + options := ¬arize.Options{ + File: c.Args().Get(0), + BundleID: c.String("bundle-id"), + Username: c.String("ac-username"), + Password: c.String("ac-password"), + Provider: c.String("ac-provider"), + Staple: c.Bool("staple"), + } + + if f := c.String("plan"); f != "" { + p, err := plan.Load(f) + if err != nil { + return err + } + + if p.Output != nil { + options.File = filepath.Join( + p.Output.Directory, p.Output.DiskImage, + ) + } + } + + return notarize.Notarize(c.Context, options) +} diff --git a/pkg/notarize/notarize.go b/pkg/notarize/notarize.go new file mode 100644 index 0000000..eac1376 --- /dev/null +++ b/pkg/notarize/notarize.go @@ -0,0 +1,98 @@ +package notarize + +import ( + "context" + "os/exec" + "path/filepath" + "sync" + "time" + + "github.com/hashicorp/go-hclog" + "github.com/mitchellh/gon/notarize" + "github.com/mitchellh/gon/staple" +) + +type Options struct { + File string + BundleID string + Username string + Password string + Provider string + Staple bool +} + +func Notarize(ctx context.Context, opts *Options) error { + logger := hclog.FromContext(ctx).Named("notarize") + + notarizeOpts := ¬arize.Options{ + File: opts.File, + BundleId: opts.BundleID, + Username: opts.Username, + Password: opts.Password, + Provider: opts.Provider, + BaseCmd: exec.CommandContext(ctx, ""), + Status: &status{ + Lock: &sync.Mutex{}, + Logger: logger, + }, + } + + logger.Info("notarizing", "file", filepath.Base(opts.File)) + + info, err := notarize.Notarize(ctx, notarizeOpts) + if err != nil { + return err + } + + logger.Info( + "notarization complete", + "status", info.Status, + "message", info.StatusMessage, + ) + + if opts.Staple { + logger.Info("stapling", "file", filepath.Base(opts.File)) + err := staple.Staple(ctx, &staple.Options{ + File: opts.File, + BaseCmd: exec.CommandContext(ctx, ""), + }) + if err != nil { + return err + } + } + + return nil +} + +type status struct { + Lock *sync.Mutex + Logger hclog.Logger + + lastStatusTime time.Time +} + +func (s *status) Submitting() { + s.Lock.Lock() + defer s.Lock.Unlock() + + s.Logger.Info("submitting file for notarization...") +} + +func (s *status) Submitted(uuid string) { + s.Lock.Lock() + defer s.Lock.Unlock() + + s.Logger.Info("submitted") + s.Logger.Debug("request", "uuid", uuid) + s.Logger.Info("waiting for result from Apple...") +} + +func (s *status) Status(info notarize.Info) { + s.Lock.Lock() + defer s.Lock.Unlock() + + if time.Now().After(s.lastStatusTime.Add(60 * time.Second)) { + s.lastStatusTime = time.Now() + s.Logger.Info("status update", "status", info.Status) + } +} From 55f35e11462db1513239a09703b0a0c1865eaeab Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Thu, 27 May 2021 01:40:53 +0100 Subject: [PATCH 06/10] chore(package): add dmgbuild helper package to execute dmgbuild --- pkg/dmgbuild/dmgbuild.go | 67 +++++ pkg/dmgbuild/icon_view.go | 85 +++++++ pkg/dmgbuild/license.go | 183 ++++++++++++++ pkg/dmgbuild/list_view.go | 154 ++++++++++++ pkg/dmgbuild/settings.go | 256 ++++++++++++++++++++ pkg/dmgbuild/settings_test.go | 444 ++++++++++++++++++++++++++++++++++ pkg/dmgbuild/window.go | 83 +++++++ 7 files changed, 1272 insertions(+) create mode 100644 pkg/dmgbuild/dmgbuild.go create mode 100644 pkg/dmgbuild/icon_view.go create mode 100644 pkg/dmgbuild/license.go create mode 100644 pkg/dmgbuild/list_view.go create mode 100644 pkg/dmgbuild/settings.go create mode 100644 pkg/dmgbuild/settings_test.go create mode 100644 pkg/dmgbuild/window.go diff --git a/pkg/dmgbuild/dmgbuild.go b/pkg/dmgbuild/dmgbuild.go new file mode 100644 index 0000000..3348512 --- /dev/null +++ b/pkg/dmgbuild/dmgbuild.go @@ -0,0 +1,67 @@ +package dmgbuild + +import ( + "context" + "fmt" + "os" + "os/exec" + "strings" + + "github.com/hashicorp/go-hclog" +) + +func Build(ctx context.Context, settings *Settings) error { + logger := hclog.NewNullLogger() + if settings.Logger == nil { + logger = settings.Logger + } + + if !strings.HasSuffix(logger.Name(), "dmgbuild") { + logger = logger.Named("dmgbuild") + } + + if settings == nil { + return fmt.Errorf("no settings provided") + } + + _, err := os.Stat(settings.Filename) + if !os.IsNotExist(err) { + return fmt.Errorf("output dmg exists: %s", settings.Filename) + } + + baseCmd := settings.Command + if baseCmd == "" { + path, err2 := exec.LookPath("dmgbuild") + if err2 != nil { + return err2 + } + baseCmd = path + } + + file, err := settings.TempFile() + if err != nil { + return err + } + defer os.Remove(file) + + args := []string{"-s", file, settings.VolumeName, settings.Filename} + + if logger.IsDebug() { + content, err := os.ReadFile(file) + if err != nil { + return err + } + logger.Debug("using settings", file, string(content)) + logger.Debug("executing", "command", baseCmd, "args", args) + } + + cmd := exec.CommandContext(ctx, baseCmd, args...) + if settings.Stdout != nil { + cmd.Stdout = settings.Stdout + } + if settings.Stderr != nil { + cmd.Stderr = settings.Stderr + } + + return cmd.Run() +} diff --git a/pkg/dmgbuild/icon_view.go b/pkg/dmgbuild/icon_view.go new file mode 100644 index 0000000..931e4ed --- /dev/null +++ b/pkg/dmgbuild/icon_view.go @@ -0,0 +1,85 @@ +package dmgbuild + +import "fmt" + +type arrageOrder string + +//nolint:golint +var ( + NameOrder arrageOrder = "name" + DateModifiedOrder arrageOrder = "date-modified" + DateCreatedOrder arrageOrder = "date-created" + DateAddedOrder arrageOrder = "date-added" + DateLastOpenedOrder arrageOrder = "date-last-opened" + SizeOrder arrageOrder = "size" + KindOrder arrageOrder = "kind" + LabelOrder arrageOrder = "label" +) + +type labelPosition string + +//nolint:golint +var ( + LabelBottom labelPosition = "bottom" + LabelRight labelPosition = "right" +) + +type IconView struct { + ArrangeBy arrageOrder + GridOffsetX int + GridOffsetY int + GridSpacing float32 + ScrollPosX float32 + ScrollPosY float32 + LabelPosition labelPosition + IconSize float32 + TextSize float32 +} + +func NewIconView() IconView { + return IconView{ + GridOffsetX: 0, + GridOffsetY: 0, + GridSpacing: 100, + ScrollPosX: 0.0, + ScrollPosY: 0.0, + LabelPosition: LabelBottom, + IconSize: 128, + TextSize: 16, + } +} + +func (s *IconView) Render() []string { + r := []string{} + + if s.ArrangeBy != "" { + r = append(r, "arrange_by = "+pyStr(string(s.ArrangeBy))+"\n") + } + if s.GridOffsetX > 0 || s.GridOffsetY > 0 { + r = append(r, fmt.Sprintf( + "grid_offset = (%d, %d)\n", + s.GridOffsetX, s.GridOffsetY, + )) + } + if s.GridSpacing > 0 { + r = append(r, fmt.Sprintf("grid_spacing = %.2f\n", s.GridSpacing)) + } + if s.ScrollPosX > 0 || s.ScrollPosY > 0 { + r = append(r, fmt.Sprintf( + "scroll_position = (%.2f, %.2f)\n", + s.ScrollPosX, s.ScrollPosY, + )) + } + if s.LabelPosition != "" { + r = append(r, "label_position = "+pyStr(string(s.LabelPosition))+"\n") + } + + if s.IconSize > 0 { + r = append(r, fmt.Sprintf("icon_size = %.2f\n", s.IconSize)) + } + if s.TextSize > 0 { + r = append(r, fmt.Sprintf("text_size = %.2f\n", s.TextSize)) + } + + return r +} diff --git a/pkg/dmgbuild/license.go b/pkg/dmgbuild/license.go new file mode 100644 index 0000000..92f0499 --- /dev/null +++ b/pkg/dmgbuild/license.go @@ -0,0 +1,183 @@ +package dmgbuild + +import ( + "fmt" + "sort" + "strings" +) + +type locale string + +//nolint:golint +var ( + LocaleAfZA locale = "af_ZA" + LocaleAr locale = "ar" + LocaleBeBY locale = "be_BY" + LocaleBgBG locale = "bg_BG" + LocaleBn locale = "bn" + LocaleBo locale = "bo" + LocaleBr locale = "br" + LocaleCaES locale = "ca_ES" + LocaleCsCZ locale = "cs_CZ" + LocaleCy locale = "cy" + LocaleDaDK locale = "da_DK" + LocaleDeAT locale = "de_AT" + LocaleDeCH locale = "de_CH" + LocaleDeDE locale = "de_DE" + LocaleDzBT locale = "dz_BT" + LocaleElCY locale = "el_CY" + LocaleElGR locale = "el_GR" + LocaleEnAU locale = "en_AU" + LocaleEnCA locale = "en_CA" + LocaleEnGB locale = "en_GB" + LocaleEnIE locale = "en_IE" + LocaleEnSG locale = "en_SG" + LocaleEnUS locale = "en_US" + LocaleEo locale = "eo" + LocaleEs419 locale = "es_419" + LocaleEsES locale = "es_ES" + LocaleEtEE locale = "et_EE" + LocaleFaIR locale = "fa_IR" + LocaleFiFI locale = "fi_FI" + LocaleFoFO locale = "fo_FO" + LocaleFr001 locale = "fr_001" + LocaleFrBE locale = "fr_BE" + LocaleFrCA locale = "fr_CA" + LocaleFrCH locale = "fr_CH" + LocaleFrFR locale = "fr_FR" + LocaleGaLatgIE locale = "ga-Latg_IE" + LocaleGaIE locale = "ga_IE" + LocaleGd locale = "gd" + LocaleGrc locale = "grc" + LocaleGuIN locale = "gu_IN" + LocaleGv locale = "gv" + LocaleHeIL locale = "he_IL" + LocaleHiIN locale = "hi_IN" + LocaleHrHR locale = "hr_HR" + LocaleHuHU locale = "hu_HU" + LocaleHyAM locale = "hy_AM" + LocaleIsIS locale = "is_IS" + LocaleItCH locale = "it_CH" + LocaleItIT locale = "it_IT" + LocaleIuCA locale = "iu_CA" + LocaleJaJP locale = "ja_JP" + LocaleKaGE locale = "ka_GE" + LocaleKl locale = "kl" + LocaleKoKR locale = "ko_KR" + LocaleLtLT locale = "lt_LT" + LocaleLvLV locale = "lv_LV" + LocaleMkMK locale = "mk_MK" + LocaleMrIN locale = "mr_IN" + LocaleMtMT locale = "mt_MT" + LocaleNbNO locale = "nb_NO" + LocaleNeNP locale = "ne_NP" + LocaleNlBE locale = "nl_BE" + LocaleNlNL locale = "nl_NL" + LocaleNnNO locale = "nn_NO" + LocalePa locale = "pa" + LocalePlPL locale = "pl_PL" + LocalePtBR locale = "pt_BR" + LocalePtPT locale = "pt_PT" + LocaleRoRO locale = "ro_RO" + LocaleRuRU locale = "ru_RU" + LocaleSe locale = "se" + LocaleSkSK locale = "sk_SK" + LocaleSlSI locale = "sl_SI" + LocaleSrRS locale = "sr_RS" + LocaleSvSE locale = "sv_SE" + LocaleThTH locale = "th_TH" + LocaleToTO locale = "to_TO" + LocaleTrTR locale = "tr_TR" + LocaleUkUA locale = "uk_UA" + LocaleUrIN locale = "ur_IN" + LocaleUrPK locale = "ur_PK" + LocaleUzUZ locale = "uz_UZ" + LocaleViVN locale = "vi_VN" + LocaleZhCN locale = "zh_CN" + LocaleZhTW locale = "zh_TW" +) + +type Buttons struct { + LanguageName string + Agree string + Disagree string + Print string + Save string + Message string +} + +type License struct { + DefaultLanguage locale + Licenses map[locale]string + Buttons map[locale]Buttons +} + +func NewLicense() License { + return License{} +} + +func (s *License) Render() []string { + var l []string + + if s.DefaultLanguage != "" { + l = append(l, + "\"default-language\": "+pyStr(string(s.DefaultLanguage)), + ) + } + + if len(s.Licenses) > 0 { + var items []string + for k, v := range s.Licenses { + items = append(items, fmt.Sprintf( + "%s: %s", pyStr(string(k)), pyMStr(v), + )) + } + sort.SliceStable(items, func(i, j int) bool { + return items[i] < items[j] + }) + l = append(l, + "\"licenses\": {\n "+ + strings.Join(items, ",\n ")+ + "\n }", + ) + } + + if len(s.Buttons) > 0 { + var items []string + for k, v := range s.Buttons { + items = append(items, fmt.Sprintf( + "%s: (\n"+ + " %s,\n"+ + " %s,\n"+ + " %s,\n"+ + " %s,\n"+ + " %s,\n"+ + " %s\n"+ + " )", + pyStr(string(k)), + pyStr(v.LanguageName), + pyStr(v.Agree), + pyStr(v.Disagree), + pyStr(v.Print), + pyStr(v.Save), + pyStr(v.Message), + )) + } + sort.SliceStable(items, func(i, j int) bool { + return items[i] < items[j] + }) + l = append(l, + "\"buttons\": {\n "+ + strings.Join(items, ",\n ")+ + "\n }", + ) + } + + if len(l) == 0 { + return []string{} + } + + return []string{ + "license = {\n " + strings.Join(l, ",\n ") + "\n}\n", + } +} diff --git a/pkg/dmgbuild/list_view.go b/pkg/dmgbuild/list_view.go new file mode 100644 index 0000000..b3f5c01 --- /dev/null +++ b/pkg/dmgbuild/list_view.go @@ -0,0 +1,154 @@ +package dmgbuild + +import ( + "fmt" + "sort" + "strings" +) + +type listColumn string + +//nolint:golint +var ( + NameColumn listColumn = "name" + DateModifiedColumn listColumn = "date-modified" + DateCreatedColumn listColumn = "date-created" + DateAddedColumn listColumn = "date-added" + DateLastOpenedColumn listColumn = "date-last-opened" + SizeColumn listColumn = "size" + KindColumn listColumn = "kind" + LabelColumn listColumn = "label" + VersionColumn listColumn = "version" + CommentsColumn listColumn = "comments" +) + +type direction string + +//nolint:golint +var ( + Ascending direction = "ascending" + Descending direction = "descending" +) + +type ListView struct { + SortBy listColumn + ScrollPosX int + ScrollPosY int + IconSize float32 + TextSize float32 + UseRelativeDates bool + CalculateAllSizes bool + Columns []listColumn + ColumnWidths map[listColumn]int + ColumnSortDirections map[listColumn]direction +} + +func NewListView() ListView { + return ListView{ + SortBy: NameColumn, + IconSize: 16, + TextSize: 12, + UseRelativeDates: true, + Columns: []listColumn{ + NameColumn, + DateModifiedColumn, + SizeColumn, + KindColumn, + DateAddedColumn, + }, + ColumnWidths: map[listColumn]int{ + (NameColumn): 300, + (DateModifiedColumn): 181, + (DateCreatedColumn): 181, + (DateAddedColumn): 181, + (DateLastOpenedColumn): 181, + (SizeColumn): 97, + (KindColumn): 115, + (LabelColumn): 100, + (VersionColumn): 75, + (CommentsColumn): 300, + }, + ColumnSortDirections: map[listColumn]direction{ + (NameColumn): Ascending, + (DateModifiedColumn): Descending, + (DateCreatedColumn): Descending, + (DateAddedColumn): Descending, + (DateLastOpenedColumn): Descending, + (SizeColumn): Descending, + (KindColumn): Ascending, + (LabelColumn): Ascending, + (VersionColumn): Ascending, + (CommentsColumn): Ascending, + }, + } +} + +func (s *ListView) Render() []string { + r := []string{} + + if s.SortBy != "" { + r = append(r, "list_sort_by = "+pyStr(string(s.SortBy))+"\n") + } + if s.ScrollPosX > 0 || s.ScrollPosY > 0 { + r = append(r, fmt.Sprintf( + "list_scroll_position = (%d, %d)\n", + s.ScrollPosX, s.ScrollPosY, + )) + } + if s.IconSize > 0 { + r = append(r, fmt.Sprintf("list_icon_size = %.2f\n", s.IconSize)) + } + if s.TextSize > 0 { + r = append(r, fmt.Sprintf("list_text_size = %.2f\n", s.TextSize)) + } + r = append(r, "list_use_relative_dates = "+pyBool(s.UseRelativeDates)+"\n") + r = append( + r, "list_calculate_all_sizes = "+pyBool(s.CalculateAllSizes)+"\n", + ) + + if len(s.Columns) > 0 { + var cols []string + for _, col := range s.Columns { + cols = append(cols, pyStr(string(col))) + } + r = append(r, + "list_columns = [\n "+strings.Join(cols, ",\n ")+"\n]\n", + ) + } + + if len(s.ColumnWidths) > 0 { + var cols []string + for col, w := range s.ColumnWidths { + cols = append(cols, fmt.Sprintf( + "%s: %d", pyStr(string(col)), w, + )) + } + sort.SliceStable(cols, func(i, j int) bool { + return cols[i] < cols[j] + }) + r = append(r, + "list_column_widths = {\n "+ + strings.Join(cols, ",\n ")+ + "\n}\n", + ) + } + + if len(s.ColumnSortDirections) > 0 { + var cols []string + for col, direction := range s.ColumnSortDirections { + cols = append(cols, fmt.Sprintf( + "%s: %s", pyStr(string(col)), pyStr(string(direction)), + )) + } + sort.SliceStable(cols, func(i, j int) bool { + return cols[i] < cols[j] + }) + r = append(r, + "list_column_sort_directions = {\n "+ + strings.Join(cols, ",\n ")+ + "\n}\n", + ) + } + + return r +} diff --git a/pkg/dmgbuild/settings.go b/pkg/dmgbuild/settings.go new file mode 100644 index 0000000..5b8c899 --- /dev/null +++ b/pkg/dmgbuild/settings.go @@ -0,0 +1,256 @@ +package dmgbuild + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "github.com/hashicorp/go-hclog" +) + +type format string + +//nolint:golint +var ( + UDROFormat format = "UDRO" // Read-only + UDCOFormat format = "UDCO" // Compressed (ADC) + UDZOFormat format = "UDZO" // Compressed (gzip) + UDBZFormat format = "UDBZ" // Compressed (bzip2) + UFBIFormat format = "UFBI" // Entire device + IPODFormat format = "IPOD" // iPod image + UDxxFormat format = "UDxx" // UDIF stub + UDSBFormat format = "UDSB" // Sparse bundle + UDSPFormat format = "UDSP" // Sparse + UDRWFormat format = "UDRW" // Read/write + UDTOFormat format = "UDTO" // DVD/CD master + DC42Format format = "DC42" // Disk Copy 4.2 + RdWrFormat format = "RdWr" // NDIF read/write + RdxxFormat format = "Rdxx" // NDIF read-only + ROCoFormat format = "ROCo" // NDIF Compressed + RkenFormat format = "Rken" // NDIF Compressed (KenCode) +) + +type File struct { + Path string + PosX int + PosY int + Hidden bool + HideExtension bool +} + +type Symlink struct { + Name string + Target string + PosX int + PosY int + Hidden bool + HideExtension bool +} + +type Settings struct { + // Command can be set to a custom dmgbuild executable path. If not set, + // the first "dmgbuild" executable within PATH will be used. + Command string + + // Stdout will be set as STDOUT target for dmgbuild execution if not nil. + Stdout io.Writer + + // Stderr will be set as STDERR target for dmgbuild execution if not nil. + Stderr io.Writer + + // Logger allows logging details of dmbuild process. + Logger hclog.Logger + + // dmgbuild settings + Filename string + VolumeName string + Format format + Size string + CompressionLevel int + Files []*File + Symlinks []*Symlink + Icon string + BadgeIcon string + Window Window + IconView IconView + ListView ListView + License License +} + +func NewSettings() *Settings { + return &Settings{ + Format: UDZOFormat, + CompressionLevel: 9, + Window: NewWindow(), + IconView: NewIconView(), + ListView: NewListView(), + License: NewLicense(), + } +} + +//nolint:funlen,gocyclo +// Render returns a string slice where each string is a separate settings +// statement. +func (s *Settings) Render() ([]string, error) { + r := []string{ + "# -*- coding: utf-8 -*-\n", + "from __future__ import unicode_literals\n", + } + + if s.Filename != "" { + r = append(r, "filename = "+pyStr(s.Filename)+"\n") + } + if s.VolumeName != "" { + r = append(r, "volume_name = "+pyStr(s.VolumeName)+"\n") + } + if s.Format != "" { + r = append(r, "format = "+pyStr(string(s.Format))+"\n") + } + if s.CompressionLevel != 0 { + r = append(r, fmt.Sprintf( + "compression_level = %d\n", s.CompressionLevel, + )) + } + if s.Size != "" { + r = append(r, "size = "+pyStr(s.Size)+"\n") + } + + var files []string + var symlinks []string + var hide []string + var hideExt []string + var iconLoc []string + + if len(s.Files) > 0 { + for _, f := range s.Files { + files = append(files, pyStr(f.Path)) + name := filepath.Base(f.Path) + if f.PosX > 0 || f.PosY > 0 { + iconLoc = append(iconLoc, + fmt.Sprintf("%s: (%d, %d)", pyStr(name), f.PosX, f.PosY), + ) + } + if f.Hidden { + hide = append(hide, pyStr(filepath.Base(f.Path))) + } + if f.HideExtension { + hideExt = append(hideExt, pyStr(filepath.Base(f.Path))) + } + } + } + + if len(s.Symlinks) > 0 { + for _, l := range s.Symlinks { + symlinks = append(symlinks, pyStr(l.Name)+": "+pyStr(l.Target)) + if l.PosX > 0 || l.PosY > 0 { + iconLoc = append(iconLoc, + fmt.Sprintf("%s: (%d, %d)", pyStr(l.Name), l.PosX, l.PosY), + ) + } + if l.Hidden { + hide = append(hide, pyStr(l.Name)) + } + if l.HideExtension { + hideExt = append(hideExt, pyStr(l.Name)) + } + } + } + + if len(files) > 0 { + r = append(r, + "files = [\n "+strings.Join(files, ",\n ")+"\n]\n", + ) + } + if len(symlinks) > 0 { + r = append(r, + "symlinks = {\n "+strings.Join(symlinks, ",\n ")+"\n}\n", + ) + } + if len(hide) > 0 { + r = append(r, + "hide = [\n "+strings.Join(hide, ",\n ")+"\n]\n", + ) + } + if len(hideExt) > 0 { + r = append(r, + "hide_extensions = [\n "+strings.Join(hideExt, ",\n ")+ + "\n]\n", + ) + } + if len(iconLoc) > 0 { + r = append(r, + "icon_locations = {\n "+strings.Join(iconLoc, ",\n ")+"\n}\n", + ) + } + + if s.Icon != "" { + r = append(r, "icon = "+pyStr(s.Icon)+"\n") + } + if s.BadgeIcon != "" { + r = append(r, "badge_icon = "+pyStr(s.BadgeIcon)+"\n") + } + + r = append(r, s.Window.Render()...) + r = append(r, s.IconView.Render()...) + r = append(r, s.ListView.Render()...) + r = append(r, s.License.Render()...) + + return r, nil +} + +func (s *Settings) Write(w io.Writer) error { + out, err := s.Render() + if err != nil { + return err + } + + for _, o := range out { + _, err := w.Write([]byte(o)) + if err != nil { + return err + } + } + + return nil +} + +func (s *Settings) TempFile() (string, error) { + f, err := os.CreateTemp("", "*.dmgbuild.settings.py") + if err != nil { + return "", err + } + defer f.Close() + + err = s.Write(f) + if err != nil { + return "", err + } + + return f.Name(), nil +} + +func pyStr(s string) string { + s = strings.ReplaceAll(s, `\`, `\\`) + s = strings.ReplaceAll(s, `"`, `\"`) + s = strings.ReplaceAll(s, "\r", `\r`) + s = strings.ReplaceAll(s, "\n", `\n`) + + return `"` + s + `"` +} + +func pyMStr(s string) string { + s = strings.ReplaceAll(s, `\`, `\\`) + s = strings.ReplaceAll(s, `"`, `\"`) + + return `"""` + s + `"""` +} + +func pyBool(v bool) string { + if v { + return "True" + } + + return "False" +} diff --git a/pkg/dmgbuild/settings_test.go b/pkg/dmgbuild/settings_test.go new file mode 100644 index 0000000..e3ba25b --- /dev/null +++ b/pkg/dmgbuild/settings_test.go @@ -0,0 +1,444 @@ +package dmgbuild + +import ( + "bytes" + "strings" + "testing" + + "github.com/jimeh/undent" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSettings_Write(t *testing.T) { + test := []struct { + name string + entitlements *Settings + want string + }{ + { + name: "empty", + entitlements: &Settings{}, + want: undent.String(` + # -*- coding: utf-8 -*- + from __future__ import unicode_literals + show_status_bar = False + show_tab_view = False + show_toolbar = False + show_pathbar = False + show_sidebar = False + show_icon_preview = False + show_item_info = False + include_icon_view_settings = False + include_list_view_settings = False + list_use_relative_dates = False + list_calculate_all_sizes = False`, + ), + }, + { + name: "full", + entitlements: &Settings{ + Filename: "/builds/Emacs.2021-05-25.f4dc646.master.dmg", + VolumeName: "Emacs.2021-05-25.f4dc646.master", + Format: UDBZFormat, + CompressionLevel: 8, + Size: "100m", + Files: []*File{ + { + Path: "/builds/Emacs.app", + PosX: 200, + PosY: 200, + }, + { + Path: "/builds/README.rtf", + PosX: 200, + PosY: 300, + HideExtension: true, + }, + { + Path: "/builds/hide-me.png", + Hidden: true, + }, + }, + Symlinks: []*Symlink{ + { + Name: "Applications", + Target: "/Applications", + PosX: 400, + PosY: 400, + }, + { + Name: "QuickLook", + Target: "/Library/QuickLook", + PosX: 500, + PosY: 400, + Hidden: true, + }, + { + Name: "System", + Target: "/System", + HideExtension: true, + }, + }, + Icon: "/opt/misc/assets/volIcon.icns", + BadgeIcon: "/builds/Emacs.app/Contents/Resources/Icon.icns", + Window: Window{ + PoxX: 200, + PosY: 250, + Width: 680, + Height: 446, + Background: "/opt/misc/assets/bg.tif", + ShowStatusBar: true, + ShowTabView: true, + ShowToolbar: true, + ShowPathbar: true, + ShowSidebar: true, + SidebarWidth: 165, + DefaultView: list, + ShowIconPreview: true, + ShowItemInfo: true, + IncludeIconViewSettings: true, + IncludeListViewSettings: true, + }, + IconView: IconView{ + ArrangeBy: NameOrder, + GridOffsetX: 42, + GridOffsetY: 43, + GridSpacing: 44.5, + ScrollPosX: 4.5, + ScrollPosY: 5.5, + LabelPosition: LabelBottom, + IconSize: 160, + TextSize: 15, + }, + ListView: ListView{ + SortBy: NameColumn, + ScrollPosX: 7, + ScrollPosY: 8, + IconSize: 16, + TextSize: 12, + UseRelativeDates: true, + CalculateAllSizes: true, + Columns: []listColumn{ + NameColumn, + DateModifiedColumn, + DateCreatedColumn, + DateAddedColumn, + DateLastOpenedColumn, + SizeColumn, + KindColumn, + LabelColumn, + VersionColumn, + CommentsColumn, + }, + ColumnWidths: map[listColumn]int{ + (NameColumn): 300, + (DateModifiedColumn): 181, + (DateCreatedColumn): 181, + (DateAddedColumn): 181, + (DateLastOpenedColumn): 181, + (SizeColumn): 97, + (KindColumn): 115, + (LabelColumn): 100, + (VersionColumn): 75, + (CommentsColumn): 300, + }, + ColumnSortDirections: map[listColumn]direction{ + (NameColumn): Ascending, + (DateModifiedColumn): Descending, + (DateCreatedColumn): Descending, + (DateAddedColumn): Descending, + (DateLastOpenedColumn): Descending, + (SizeColumn): Descending, + (KindColumn): Ascending, + (LabelColumn): Ascending, + (VersionColumn): Ascending, + (CommentsColumn): Ascending, + }, + }, + License: License{ + DefaultLanguage: LocaleEnUS, + Licenses: map[locale]string{ + //nolint:lll + (LocaleEnGB): undent.String(` + {\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf820 + {\fonttbl\f0\fnil\fcharset0 Helvetica-Bold;\f1\fnil\fcharset0 Helvetica;} + {\colortbl;\red255\green255\blue255;\red0\green0\blue0;} + {\*\expandedcolortbl;;\cssrgb\c0\c0\c0;} + \paperw11905\paperh16837\margl1133\margr1133\margb1133\margt1133 + \deftab720 + \pard\pardeftab720\sa160\partightenfactor0 + \f0\b\fs60 \cf2 \expnd0\expndtw0\kerning0 + \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 Test License\ + \pard\pardeftab720\sa160\partightenfactor0 + \fs36 \cf2 \strokec2 What is this?\ + \pard\pardeftab720\sa160\partightenfactor0 + \f1\b0\fs22 \cf2 \strokec2 This is the English license. It says what you are allowed to do with this software.\ + \ + }`, + ), + //nolint:lll + (LocaleSe): undent.String(` + {\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf820 + {\fonttbl\f0\fnil\fcharset0 Helvetica-Bold;\f1\fnil\fcharset0 Helvetica;} + {\colortbl;\red255\green255\blue255;\red0\green0\blue0;} + {\*\expandedcolortbl;;\cssrgb\c0\c0\c0;} + \paperw11905\paperh16837\margl1133\margr1133\margb1133\margt1133 + \deftab720 + \pard\pardeftab720\sa160\partightenfactor0 + \f0\b\fs60 \cf2 \expnd0\expndtw0\kerning0 + \up0 \nosupersub \ulnone \outl0\strokewidth0 \strokec2 Test License\ + \pard\pardeftab720\sa160\partightenfactor0 + \fs36 \cf2 \strokec2 What is this?\ + \pard\pardeftab720\sa160\partightenfactor0 + \f1\b0\fs22 \cf2 \strokec2 Detta är den engelska licensen. Det stÃ¥r vad du fÃ¥r göra med den här programvaran.\ + \ + }`, + ), + }, + Buttons: map[locale]Buttons{ + (LocaleEnGB): { + LanguageName: "English", + Agree: "Agree", + Disagree: "Disagree", + Print: "Print", + Save: "Save", + Message: "If you agree with the terms of this " + + "license, press \"Agree\" to install the " + + "software. If you do not agree, press " + + "\"Disagree\".", + }, + (LocaleSe): { + LanguageName: "Svenska", + Agree: "Godkänn", + Disagree: "HÃ¥ller inte med", + Print: "Skriv ut", + Save: "Spara", + Message: "Om du godkänner villkoren i denna " + + "licens, tryck pÃ¥ \"Godkänn\" för att " + + "installera programvaran. Om du inte hÃ¥ller " + + "med, tryck pÃ¥ \"HÃ¥ller inte med\".", + }, + }, + }, + }, + //nolint:lll + want: undent.String(` + # -*- coding: utf-8 -*- + from __future__ import unicode_literals + filename = "/builds/Emacs.2021-05-25.f4dc646.master.dmg" + volume_name = "Emacs.2021-05-25.f4dc646.master" + format = "UDBZ" + compression_level = 8 + size = "100m" + files = [ + "/builds/Emacs.app", + "/builds/README.rtf", + "/builds/hide-me.png" + ] + symlinks = { + "Applications": "/Applications", + "QuickLook": "/Library/QuickLook", + "System": "/System" + } + hide = [ + "hide-me.png", + "QuickLook" + ] + hide_extensions = [ + "README.rtf", + "System" + ] + icon_locations = { + "Emacs.app": (200, 200), + "README.rtf": (200, 300), + "Applications": (400, 400), + "QuickLook": (500, 400) + } + icon = "/opt/misc/assets/volIcon.icns" + badge_icon = "/builds/Emacs.app/Contents/Resources/Icon.icns" + background = "/opt/misc/assets/bg.tif" + show_status_bar = True + show_tab_view = True + show_toolbar = True + show_pathbar = True + show_sidebar = True + sidebar_width = 165 + default_view = "list-view" + window_rect = ((200, 250), (680, 446)) + show_icon_preview = True + show_item_info = True + include_icon_view_settings = True + include_list_view_settings = True + arrange_by = "name" + grid_offset = (42, 43) + grid_spacing = 44.50 + scroll_position = (4.50, 5.50) + label_position = "bottom" + icon_size = 160.00 + text_size = 15.00 + list_sort_by = "name" + list_scroll_position = (7, 8) + list_icon_size = 16.00 + list_text_size = 12.00 + list_use_relative_dates = True + list_calculate_all_sizes = True + list_columns = [ + "name", + "date-modified", + "date-created", + "date-added", + "date-last-opened", + "size", + "kind", + "label", + "version", + "comments" + ] + list_column_widths = { + "comments": 300, + "date-added": 181, + "date-created": 181, + "date-last-opened": 181, + "date-modified": 181, + "kind": 115, + "label": 100, + "name": 300, + "size": 97, + "version": 75 + } + list_column_sort_directions = { + "comments": "ascending", + "date-added": "descending", + "date-created": "descending", + "date-last-opened": "descending", + "date-modified": "descending", + "kind": "ascending", + "label": "ascending", + "name": "ascending", + "size": "descending", + "version": "ascending" + } + license = { + "default-language": "en_US", + "licenses": { + "en_GB": """{\\rtf1\\ansi\\ansicpg1252\\cocoartf1504\\cocoasubrtf820 + {\\fonttbl\\f0\\fnil\\fcharset0 Helvetica-Bold;\\f1\\fnil\\fcharset0 Helvetica;} + {\\colortbl;\\red255\\green255\\blue255;\\red0\\green0\\blue0;} + {\\*\\expandedcolortbl;;\\cssrgb\\c0\\c0\\c0;} + \\paperw11905\\paperh16837\\margl1133\\margr1133\\margb1133\\margt1133 + \\deftab720 + \\pard\\pardeftab720\\sa160\\partightenfactor0 + \\f0\\b\\fs60 \\cf2 \\expnd0\\expndtw0\\kerning0 + \\up0 \\nosupersub \\ulnone \\outl0\\strokewidth0 \\strokec2 Test License\\ + \\pard\\pardeftab720\\sa160\\partightenfactor0 + \\fs36 \\cf2 \\strokec2 What is this?\\ + \\pard\\pardeftab720\\sa160\\partightenfactor0 + \\f1\\b0\\fs22 \\cf2 \\strokec2 This is the English license. It says what you are allowed to do with this software.\\ + \\ + }""", + "se": """{\\rtf1\\ansi\\ansicpg1252\\cocoartf1504\\cocoasubrtf820 + {\\fonttbl\\f0\\fnil\\fcharset0 Helvetica-Bold;\\f1\\fnil\\fcharset0 Helvetica;} + {\\colortbl;\\red255\\green255\\blue255;\\red0\\green0\\blue0;} + {\\*\\expandedcolortbl;;\\cssrgb\\c0\\c0\\c0;} + \\paperw11905\\paperh16837\\margl1133\\margr1133\\margb1133\\margt1133 + \\deftab720 + \\pard\\pardeftab720\\sa160\\partightenfactor0 + \\f0\\b\\fs60 \\cf2 \\expnd0\\expndtw0\\kerning0 + \\up0 \\nosupersub \\ulnone \\outl0\\strokewidth0 \\strokec2 Test License\\ + \\pard\\pardeftab720\\sa160\\partightenfactor0 + \\fs36 \\cf2 \\strokec2 What is this?\\ + \\pard\\pardeftab720\\sa160\\partightenfactor0 + \\f1\\b0\\fs22 \\cf2 \\strokec2 Detta är den engelska licensen. Det stÃ¥r vad du fÃ¥r göra med den här programvaran.\\ + \\ + }""" + }, + "buttons": { + "en_GB": ( + "English", + "Agree", + "Disagree", + "Print", + "Save", + "If you agree with the terms of this license, press \"Agree\" to install the software. If you do not agree, press \"Disagree\"." + ), + "se": ( + "Svenska", + "Godkänn", + "HÃ¥ller inte med", + "Skriv ut", + "Spara", + "Om du godkänner villkoren i denna licens, tryck pÃ¥ \"Godkänn\" för att installera programvaran. Om du inte hÃ¥ller med, tryck pÃ¥ \"HÃ¥ller inte med\"." + ) + } + }`, + ), + }, + } + for _, tt := range test { + t.Run(tt.name, func(t *testing.T) { + var buf bytes.Buffer + + err := tt.entitlements.Write(&buf) + require.NoError(t, err) + + assert.Equal(t, tt.want, strings.TrimSpace(buf.String())) + }) + } +} + +func Test_pyStr(t *testing.T) { + tests := []struct { + name string + s string + want string + }{ + { + name: "empty", + s: "", + want: `""`, + }, + { + name: "regular string", + s: "foo-bar nope :)", + want: `"foo-bar nope :)"`, + }, + { + name: "with single quotes", + s: "john's lost 'flip-flop'", + want: `"john's lost 'flip-flop'"`, + }, + { + name: "with double quotes", + s: `john has lost a "flip-flop"`, + want: `"john has lost a \"flip-flop\""`, + }, + { + name: "with backslashes", + s: `C:\path\to\file.txt`, + want: `"C:\\path\\to\\file.txt"`, + }, + { + name: "with line-feed", + s: "hello\nworld", + want: `"hello\nworld"`, + }, + { + name: "with carriage return", + s: "hello\rworld", + want: `"hello\rworld"`, + }, + { + name: "with backslashes, single and double quotes", + s: `john's "lost" C:\path\to\file.txt`, + want: `"john's \"lost\" C:\\path\\to\\file.txt"`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := pyStr(tt.s) + + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/dmgbuild/window.go b/pkg/dmgbuild/window.go new file mode 100644 index 0000000..a9e96c3 --- /dev/null +++ b/pkg/dmgbuild/window.go @@ -0,0 +1,83 @@ +package dmgbuild + +import "fmt" + +type view string + +//nolint:golint +var ( + Icon view = "icon-view" + list view = "list-view" + Column view = "column-view" + Coverflow view = "coverflow" +) + +type Window struct { + PoxX int + PosY int + Width int + Height int + Background string + ShowStatusBar bool + ShowTabView bool + ShowToolbar bool + ShowPathbar bool + ShowSidebar bool + SidebarWidth int + DefaultView view + ShowIconPreview bool + ShowItemInfo bool + IncludeIconViewSettings bool + IncludeListViewSettings bool +} + +func NewWindow() Window { + return Window{ + PoxX: 100, + PosY: 150, + Width: 640, + Height: 280, + Background: "builtin-arrow", + DefaultView: Icon, + } +} + +func (s *Window) Render() []string { + r := []string{} + + if s.Background != "" { + r = append(r, "background = "+pyStr(s.Background)+"\n") + } + + r = append(r, "show_status_bar = "+pyBool(s.ShowStatusBar)+"\n") + r = append(r, "show_tab_view = "+pyBool(s.ShowTabView)+"\n") + r = append(r, "show_toolbar = "+pyBool(s.ShowToolbar)+"\n") + r = append(r, "show_pathbar = "+pyBool(s.ShowPathbar)+"\n") + r = append(r, "show_sidebar = "+pyBool(s.ShowSidebar)+"\n") + + if s.SidebarWidth > 0 { + r = append(r, fmt.Sprintf( + "sidebar_width = %d\n", s.SidebarWidth, + )) + } + if s.DefaultView != "" { + r = append(r, "default_view = "+pyStr(string(s.DefaultView))+"\n") + } + if s.Width > 0 && s.Height > 0 { + r = append(r, fmt.Sprintf( + "window_rect = ((%d, %d), (%d, %d))\n", + s.PoxX, s.PosY, s.Width, s.Height, + )) + } + + r = append(r, "show_icon_preview = "+pyBool(s.ShowIconPreview)+"\n") + r = append(r, "show_item_info = "+pyBool(s.ShowIconPreview)+"\n") + r = append( + r, "include_icon_view_settings = "+pyBool(s.ShowIconPreview)+"\n", + ) + r = append( + r, "include_list_view_settings = "+pyBool(s.ShowIconPreview)+"\n", + ) + + return r +} From 87ecfbcec05b46d7a30202269474612834b648f3 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Tue, 25 May 2021 02:59:40 +0100 Subject: [PATCH 07/10] feat(package): add package command to create a styled *.dmg for Emacs.app --- Makefile | 6 +- pkg/cli/cli.go | 1 + pkg/cli/notarize.go | 4 +- pkg/cli/package.go | 230 +++++++++++++++++++++++++++++++++++++ pkg/cli/sign.go | 2 +- pkg/dmg/assets/assets.go | 45 ++++++++ pkg/dmg/assets/bg.afdesign | Bin 0 -> 10242 bytes pkg/dmg/assets/bg.png | Bin 0 -> 3946 bytes pkg/dmg/assets/bg.tif | Bin 0 -> 26918 bytes pkg/dmg/assets/bg@2x.png | Bin 0 -> 7617 bytes pkg/dmg/assets/vol.icns | Bin 0 -> 198602 bytes pkg/dmg/dmg.go | 138 ++++++++++++++++++++++ pkg/dmgbuild/dmgbuild.go | 35 ++++-- 13 files changed, 448 insertions(+), 13 deletions(-) create mode 100644 pkg/cli/package.go create mode 100644 pkg/dmg/assets/assets.go create mode 100644 pkg/dmg/assets/bg.afdesign create mode 100644 pkg/dmg/assets/bg.png create mode 100644 pkg/dmg/assets/bg.tif create mode 100644 pkg/dmg/assets/bg@2x.png create mode 100644 pkg/dmg/assets/vol.icns create mode 100644 pkg/dmg/dmg.go diff --git a/Makefile b/Makefile index 9d47da3..dfb3a8a 100644 --- a/Makefile +++ b/Makefile @@ -93,7 +93,7 @@ $(BINS): $(BINDIR)/%: $(SOURCES) # Development # -TEST ?= $$(go list ./... | grep -v 'sources/') +TEST ?= $$(go list ./... | grep -v 'sources/' | grep -v 'builds/') .PHONY: clean clean: @@ -112,6 +112,10 @@ lint: $(TOOLDIR)/golangci-lint format: $(TOOLDIR)/gofumpt gofumpt -w . +.PHONY: gen +gen: + go generate $$(go list ./... | grep -v 'sources/' | grep -v 'builds/') + # # Dependencies # diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index b1eeea9..10a4fbe 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -47,6 +47,7 @@ func New(version, commit, date string) *CLI { planCmd(), signCmd(), notarizeCmd(), + packageCmd(), { Name: "version", Usage: "print the version", diff --git a/pkg/cli/notarize.go b/pkg/cli/notarize.go index f619d92..1abc44f 100644 --- a/pkg/cli/notarize.go +++ b/pkg/cli/notarize.go @@ -16,7 +16,7 @@ func notarizeCmd() *cli2.Command { Flags: []cli2.Flag{ &cli2.StringFlag{ Name: "bundle-id", - Usage: "Bundle", + Usage: "bundle identifier", Value: "org.gnu.Emacs", }, &cli2.StringFlag{ @@ -36,7 +36,7 @@ func notarizeCmd() *cli2.Command { }, &cli2.BoolFlag{ Name: "staple", - Usage: "stable file after notarization", + Usage: "staple file after notarization", Value: true, }, &cli2.StringFlag{ diff --git a/pkg/cli/package.go b/pkg/cli/package.go new file mode 100644 index 0000000..bc6243c --- /dev/null +++ b/pkg/cli/package.go @@ -0,0 +1,230 @@ +package cli + +import ( + "crypto/sha256" + "fmt" + "io" + "os" + "path/filepath" + + "github.com/hashicorp/go-hclog" + "github.com/jimeh/build-emacs-for-macos/pkg/dmg" + "github.com/jimeh/build-emacs-for-macos/pkg/notarize" + "github.com/jimeh/build-emacs-for-macos/pkg/plan" + "github.com/jimeh/build-emacs-for-macos/pkg/sign" + cli2 "github.com/urfave/cli/v2" +) + +func packageCmd() *cli2.Command { + return &cli2.Command{ + Name: "package", + Usage: "package a build directory containing Emacs.app into a dmg", + ArgsUsage: "", + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "volume-name", + Usage: "set volume name, defaults to basename of source dir", + Aliases: []string{"n"}, + }, + &cli2.BoolFlag{ + Name: "sign", + Usage: "sign Emacs.app before packaging, notarize and staple " + + "dmg after packaging", + }, + &cli2.StringFlag{ + Name: "output", + Usage: "specify output dmg file name, if not specified the " + + "output filename is based on source directory", + Aliases: []string{"o"}, + }, + &cli2.BoolFlag{ + Name: "sha256", + Usage: "create .sha256 checksum file for output dmg", + Aliases: []string{"s"}, + Value: true, + }, + &cli2.BoolFlag{ + Name: "remove-source-dir", + Usage: "remove source directory after successfully " + + "creating dmg", + Aliases: []string{"rm"}, + Value: false, + }, + &cli2.BoolFlag{ + Name: "verbose", + Usage: "verbose output", + Aliases: []string{"v"}, + Value: false, + }, + &cli2.StringFlag{ + Name: "dmgbuild", + Usage: "specify custom path to dmgbuild executable", + }, + &cli2.StringFlag{ + Name: "sign-identity", + Usage: "(with --sign) signing identity passed to codesign", + EnvVars: []string{"AC_SIGN_IDENTITY"}, + }, + &cli2.StringFlag{ + Name: "bundle-id", + Usage: "(with --sign) bundle identifier", + Value: "org.gnu.Emacs", + }, + &cli2.StringFlag{ + Name: "ac-username", + Usage: "(with --sign) Apple Connect username", + EnvVars: []string{"AC_USERNAME"}, + }, + &cli2.StringFlag{ + Name: "ac-password", + Usage: "(with --sign) Apple Connect password", + Value: "@env:AC_PASSWORD", + }, + &cli2.StringFlag{ + Name: "ac-provider", + Usage: "(with --sign) Apple Connect provider", + EnvVars: []string{"AC_PROVIDER"}, + }, + &cli2.BoolFlag{ + Name: "staple", + Usage: "(with --sign) stable after notarization", + Value: true, + }, + &cli2.StringFlag{ + Name: "plan", + Usage: "path to build plan YAML file produced by " + + "emacs-builder plan", + Aliases: []string{"p"}, + EnvVars: []string{"EMACS_BUILDER_PLAN"}, + TakesFile: true, + }, + }, + Action: actionWrapper(packageAction), + } +} + +//nolint:funlen +func packageAction(c *cli2.Context, opts *Options) error { + logger := hclog.FromContext(c.Context).Named("package") + + sourceDir := c.Args().Get(0) + doSign := c.Bool("sign") + + var p *plan.Plan + var err error + if f := c.String("plan"); f != "" { + p, err = plan.Load(f) + if err != nil { + return err + } + } + + if doSign { + app := filepath.Join(sourceDir, "Emacs.app") + + signOpts := &sign.Options{ + Identity: c.String("sign-identity"), + Options: []string{"runtime"}, + Deep: true, + Timestamp: true, + Force: true, + Verbose: c.Bool("verbose"), + } + + if p != nil { + if p.Output != nil && p.Build != nil { + app = filepath.Join( + p.Output.Directory, p.Build.Name, "Emacs.app", + ) + } + } + + if !opts.quiet { + signOpts.Output = os.Stdout + } + + err = sign.Emacs(c.Context, app, signOpts) + if err != nil { + return err + } + } + + dmgOpts := &dmg.Options{ + DMGBuild: c.String("dmgbuild"), + SourceDir: sourceDir, + VolumeName: c.String("volume-name"), + OutputFile: c.String("output"), + RemoveSourceDir: c.Bool("remove-source-dir"), + Verbose: c.Bool("verbose"), + } + + if p != nil && p.Output != nil && p.Build != nil { + dmgOpts.SourceDir = filepath.Join( + p.Output.Directory, p.Build.Name, + ) + dmgOpts.VolumeName = p.Build.Name + dmgOpts.OutputFile = filepath.Join( + p.Output.Directory, p.Output.DiskImage, + ) + } + + if !opts.quiet { + dmgOpts.Output = os.Stdout + } + + outputDMG, err := dmg.Create(c.Context, dmgOpts) + if err != nil { + return err + } + + if doSign { + notarizeOpts := ¬arize.Options{ + File: outputDMG, + BundleID: c.String("bundle-id"), + Username: c.String("ac-username"), + Password: c.String("ac-password"), + Provider: c.String("ac-provider"), + Staple: c.Bool("staple"), + } + + err = notarize.Notarize(c.Context, notarizeOpts) + if err != nil { + return err + } + } + + if c.Bool("sha256") { + sumFile := outputDMG + ".sha256" + + logger.Info("generating SHA256 checksum", "file", outputDMG) + sum, err := fileSHA256(outputDMG) + if err != nil { + return err + } + + logger.Info("checksum", "sha256", sum, "file", outputDMG) + content := fmt.Sprintf("%s %s", sum, filepath.Base(outputDMG)) + err = os.WriteFile(sumFile, []byte(content), 0o644) //nolint:gosec + if err != nil { + return err + } + logger.Info("wrote checksum", "file", sumFile) + } + + return nil +} + +func fileSHA256(filename string) (string, error) { + f, err := os.Open(filename) + if err != nil { + return "", err + } + defer f.Close() + + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + return "", err + } + + return fmt.Sprintf("%x", h.Sum(nil)), nil +} diff --git a/pkg/cli/sign.go b/pkg/cli/sign.go index cd54876..4f430d2 100644 --- a/pkg/cli/sign.go +++ b/pkg/cli/sign.go @@ -18,7 +18,7 @@ func signCmd() *cli2.Command { &cli2.StringFlag{ Name: "sign", Aliases: []string{"s"}, - Usage: "signing identity passed to codeside", + Usage: "signing identity passed to codesign", EnvVars: []string{"AC_SIGN_IDENTITY"}, Required: true, }, diff --git a/pkg/dmg/assets/assets.go b/pkg/dmg/assets/assets.go new file mode 100644 index 0000000..0b5b596 --- /dev/null +++ b/pkg/dmg/assets/assets.go @@ -0,0 +1,45 @@ +package assets + +import ( + _ "embed" + "os" +) + +//go:generate tiffutil -cathidpicheck bg.png bg@2x.png -out bg.tif + +// Background is a raw byte slice of bytes of bg.tiff +//go:embed bg.tif +var Background []byte + +// BackgroundTempFile writes Background to a temporary file on disk, returning +// the resulting file path. The returned filepath should be deleted with +// os.Remove() when no longer needed. +func BackgroundTempFile() (string, error) { + return tempFile("*-emacs-bg.tif", Background) +} + +// Icon is a raw byte slice of bytes of vol.icns +//go:embed vol.icns +var Icon []byte + +// IconTempFile writes Icon to a temporary file on disk, returning the resulting +// file path. The returned filepath should be deleted with os.Remove() when no +// longer needed. +func IconTempFile() (string, error) { + return tempFile("*-emacs-vol.icns", Icon) +} + +func tempFile(pattern string, content []byte) (string, error) { + f, err := os.CreateTemp("", pattern) + if err != nil { + return "", err + } + defer f.Close() + + _, err = f.Write(content) + if err != nil { + return "", err + } + + return f.Name(), nil +} diff --git a/pkg/dmg/assets/bg.afdesign b/pkg/dmg/assets/bg.afdesign new file mode 100644 index 0000000000000000000000000000000000000000..88deb582a2c67887624237a2afec46e3bced778c GIT binary patch literal 10242 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 LH02v)tt0*iH%_&R literal 0 HcmV?d00001 diff --git a/pkg/dmg/assets/bg.png b/pkg/dmg/assets/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..2bef62d3e7c4ec63a3a30d3e15dca99e4335fc2d GIT binary patch literal 3946 zcmeHKdr(tn7QcX&M{C1E>jS4I2D__^$xVVFxs!)9P>4vN5T08fA-M@xlH8cwNP-YV zQCeDxtnH3g7R$2hC}pX&y9>&*P;uD`6kV{Qyu`xFNDV44A+TQp@~C$A@6MQ+Z*tH5 zopZi(e&>#HGfDhEoK%7Nz*medr7- z&xOL#%H&8yz}s`iK;lvp2||OwaB^}oJ=vR%YZWk)&1S<47R+MNfCf!xR1*>dO|A2^ zx|sD5fa;`LOhaI}nqu`SNx=04mr4aVWzM-wI`3Pf*D7tEWl|VbqAFBP=wK$D2`|=1 z4cJ07YTX=NfH>HS0CmO^bpn(BjJg$hMqQJL6SyuB*USgC|Gnfd2jj*i{XSIX^b(sUr@&e165Y4-V%r>2D7NlG zBvNZ(xKxc6m+7Ub%tj?hVHVZlaw1uxMg0|^vA9%!xf}x}G*ZBbV+u8@r7-Di`YiqP zHpz)7@b~kK!i$r68XO0HCj8ml7cCQDH~S7ODX{I}`E>_``Gtw9!Isp5by#@1XgyfD z85n4WXPN+lHs_uU3A1c|(c(o3rodu-vv^Tm8cgdH>0+Mg2{c zU2BE^_*e8h34J#X)g1imh3M?yMp2ym+A{-{#=RSK>Vbk5OVSi#GsiSeyhv(?|R z*q$u6(Wa}-6P%WE%PK7cDx&Y{X5yO?>cpRwY&UFc&B-^P zHIHu>l^K6mE)-r~c_i$J<>HR7;?;U=_ulr!XBUk>7OT@+Ukf`2~WrOmrzRrJ`=@W-*+Asu^;Rlf9ZazqIARL$-Cfp%~=y1r-PuE-L1zC`ZRwv1UYRI2Kb8& z`9qy>Set5f?LN&ViB@oU+1A268ns9M+xB>XZ+6C5T|;I=(s>UNGfAg@X(s&7CpP-^ za58e3ALWJ_{myrfJ;Da6zm00HuK4lcsW)=3cthLjb3R`OK_}MrIv#X=ab9rni|&Ce zJA}iz-PxHoeCP7<--LBl8g&|trp?{%#^w74PW9lLgEKe#`}-Rj8g8~IS_-NTjHykg zX_p}TQs>^R!Zo>9a>@MZ$M>#J2!+S+#4n07V>*N&{8 zVr(f>cczRCw%xrr>fl}QL~?9&bhLnoiJNhSPLC4sG?wIK4>ai-g|OjB&aBFu%6<~f6by8S+#QI8UE{xYxwJnNltw6Ssuf4 z%C+!G?WW$W-pI6`56$(p=Xja|bNw;!m0_;mbB@Olj!RC6$>W~ndl`0s|MZE6e;IT* zuAE|QyLIbUF=;9- WavmKLsP|g`A`1gW0i|#4IrLvdE0mr9 literal 0 HcmV?d00001 diff --git a/pkg/dmg/assets/bg.tif b/pkg/dmg/assets/bg.tif new file mode 100644 index 0000000000000000000000000000000000000000..38347c1f8887718cdc31e2826a832cdebfb13464 GIT binary patch literal 26918 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 literal 0 HcmV?d00001 diff --git a/pkg/dmg/assets/vol.icns b/pkg/dmg/assets/vol.icns new file mode 100644 index 0000000000000000000000000000000000000000..01265a2720eed94d4341487996d992e9b8b34c63 GIT binary patch literal 198602 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 Tv&bPo0|2s;iV{^~hC%-iUOuv> literal 0 HcmV?d00001 diff --git a/pkg/dmg/dmg.go b/pkg/dmg/dmg.go new file mode 100644 index 0000000..8ea665f --- /dev/null +++ b/pkg/dmg/dmg.go @@ -0,0 +1,138 @@ +package dmg + +import ( + "context" + "io" + "os" + "path/filepath" + + "github.com/hashicorp/go-hclog" + "github.com/jimeh/build-emacs-for-macos/pkg/dmg/assets" + "github.com/jimeh/build-emacs-for-macos/pkg/dmgbuild" +) + +type Options struct { + DMGBuild string + + SourceDir string + VolumeName string + OutputFile string + RemoveSourceDir bool + Verbose bool + Output io.Writer +} + +//nolint:funlen +// Create will create a *.dmg disk image as specified by the given Options. +func Create(ctx context.Context, opts *Options) (string, error) { + logger := hclog.FromContext(ctx).Named("package") + + sourceDir, err := filepath.Abs(opts.SourceDir) + if err != nil { + return "", err + } + + appBundle := filepath.Join(sourceDir, "Emacs.app") + _, err = os.Stat(appBundle) + if err != nil { + return "", err + } + + volIcon, err := assets.IconTempFile() + if err != nil { + return "", err + } + defer os.Remove(volIcon) + + bgImg, err := assets.BackgroundTempFile() + if err != nil { + return "", err + } + defer os.Remove(bgImg) + + volName := opts.VolumeName + if volName == "" { + volName = filepath.Base(sourceDir) + } + + outputDMG := opts.OutputFile + if outputDMG == "" { + outputDMG = sourceDir + ".dmg" + } + + settings := &dmgbuild.Settings{ + Logger: logger, + + Filename: outputDMG, + VolumeName: volName, + Icon: volIcon, + Format: dmgbuild.UDZOFormat, + CompressionLevel: 9, + Files: []*dmgbuild.File{ + { + Path: appBundle, + PosX: 170, + PosY: 200, + }, + }, + Symlinks: []*dmgbuild.Symlink{ + { + Name: "Applications", + Target: "/Applications", + PosX: 510, + PosY: 200, + }, + }, + Window: dmgbuild.Window{ + Background: bgImg, + PoxX: 200, + PosY: 200, + Width: 680, + Height: 446, + DefaultView: dmgbuild.Icon, + }, + IconView: dmgbuild.IconView{ + IconSize: 160, + TextSize: 16, + }, + } + + copyingFile := filepath.Join(sourceDir, "COPYING") + fi, err := os.Stat(copyingFile) + if err != nil && !os.IsNotExist(err) { + return "", err + } else if err == nil && fi.Mode().IsRegular() { + settings.Files = append(settings.Files, &dmgbuild.File{ + Path: copyingFile, + PosX: 340, + PosY: 506, + }) + } + + if opts.Output != nil { + settings.Stdout = opts.Output + settings.Stderr = opts.Output + } + + logger.Info("creating dmg", "file", filepath.Base(outputDMG)) + + err = dmgbuild.Build(ctx, settings) + if err != nil { + return "", err + } + + if opts.RemoveSourceDir { + dir, err := filepath.Abs(opts.SourceDir) + if err != nil { + return "", err + } + + logger.Info("removing", "source-dir", dir) + err = os.RemoveAll(dir) + if err != nil { + return "", err + } + } + + return outputDMG, nil +} diff --git a/pkg/dmgbuild/dmgbuild.go b/pkg/dmgbuild/dmgbuild.go index 3348512..57e72ef 100644 --- a/pkg/dmgbuild/dmgbuild.go +++ b/pkg/dmgbuild/dmgbuild.go @@ -11,8 +11,12 @@ import ( ) func Build(ctx context.Context, settings *Settings) error { + if settings == nil { + return fmt.Errorf("no settings provided") + } + logger := hclog.NewNullLogger() - if settings.Logger == nil { + if settings.Logger != nil { logger = settings.Logger } @@ -20,10 +24,6 @@ func Build(ctx context.Context, settings *Settings) error { logger = logger.Named("dmgbuild") } - if settings == nil { - return fmt.Errorf("no settings provided") - } - _, err := os.Stat(settings.Filename) if !os.IsNotExist(err) { return fmt.Errorf("output dmg exists: %s", settings.Filename) @@ -47,9 +47,9 @@ func Build(ctx context.Context, settings *Settings) error { args := []string{"-s", file, settings.VolumeName, settings.Filename} if logger.IsDebug() { - content, err := os.ReadFile(file) - if err != nil { - return err + content, err2 := os.ReadFile(file) + if err2 != nil { + return err2 } logger.Debug("using settings", file, string(content)) logger.Debug("executing", "command", baseCmd, "args", args) @@ -63,5 +63,22 @@ func Build(ctx context.Context, settings *Settings) error { cmd.Stderr = settings.Stderr } - return cmd.Run() + err = cmd.Run() + if err != nil { + return err + } + + f, err := os.Stat(settings.Filename) + if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("output DMG file is missing") + } + + return err + } + if !f.Mode().IsRegular() { + return fmt.Errorf("output DMG file is not a file") + } + + return nil } From 276a9da5eed618322e09fba11a486ae0d9925fdd Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Tue, 8 Jun 2021 00:13:32 +0100 Subject: [PATCH 08/10] feat(release): add release check command --- pkg/cli/cli.go | 1 + pkg/cli/release.go | 124 +++++++++++++++++++++++++++++++++++++++++++ pkg/release/check.go | 80 ++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 pkg/cli/release.go create mode 100644 pkg/release/check.go diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 10a4fbe..9d54855 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -48,6 +48,7 @@ func New(version, commit, date string) *CLI { signCmd(), notarizeCmd(), packageCmd(), + releaseCmd(), { Name: "version", Usage: "print the version", diff --git a/pkg/cli/release.go b/pkg/cli/release.go new file mode 100644 index 0000000..2c48b73 --- /dev/null +++ b/pkg/cli/release.go @@ -0,0 +1,124 @@ +package cli + +import ( + "os" + + "github.com/jimeh/build-emacs-for-macos/pkg/plan" + "github.com/jimeh/build-emacs-for-macos/pkg/release" + "github.com/jimeh/build-emacs-for-macos/pkg/repository" + cli2 "github.com/urfave/cli/v2" +) + +type releaseOptions struct { + Plan *plan.Plan + Repository *repository.Repository + Name string + GithubToken string +} + +func releaseCmd() *cli2.Command { + tokenDefaultText := "" + if len(os.Getenv("GITHUB_TOKEN")) > 0 { + tokenDefaultText = "***" + } + + return &cli2.Command{ + Name: "release", + Usage: "manage GitHub releases", + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "plan", + Usage: "path to build plan YAML file produced by " + + "emacs-builder plan", + Aliases: []string{"p"}, + EnvVars: []string{"EMACS_BUILDER_PLAN"}, + TakesFile: true, + }, + &cli2.StringFlag{ + Name: "repository", + Aliases: []string{"repo", "r"}, + Usage: "owner/name of GitHub repo to check for release, " + + "ignored if a plan is provided", + EnvVars: []string{"GITHUB_REPOSITORY"}, + Value: "jimeh/emacs-builds", + }, + &cli2.StringFlag{ + Name: "name", + Aliases: []string{"n"}, + Usage: "name of release to operate on, ignored if plan " + + "is provided", + }, + &cli2.StringFlag{ + Name: "github-token", + Usage: "GitHub API Token", + EnvVars: []string{"GITHUB_TOKEN"}, + DefaultText: tokenDefaultText, + }, + }, + Subcommands: []*cli2.Command{ + releaseCheckCmd(), + }, + } +} + +func releaseActionWrapper( + f func(*cli2.Context, *Options, *releaseOptions) error, +) func(*cli2.Context) error { + return actionWrapper(func(c *cli2.Context, opts *Options) error { + rOpts := &releaseOptions{ + Name: c.String("name"), + GithubToken: c.String("github-token"), + } + + if r := c.String("repository"); r != "" { + var err error + rOpts.Repository, err = repository.NewGitHub(r) + if err != nil { + return err + } + } + + if f := c.String("plan"); f != "" { + p, err := plan.Load(f) + if err != nil { + return err + } + + rOpts.Plan = p + } + + return f(c, opts, rOpts) + }) +} + +func releaseCheckCmd() *cli2.Command { + return &cli2.Command{ + Name: "check", + Usage: "check if a GitHub release exists and has specified " + + "asset files", + ArgsUsage: "[ ...]", + Action: releaseActionWrapper(releaseCheckAction), + } +} + +func releaseCheckAction( + c *cli2.Context, + opts *Options, + rOpts *releaseOptions, +) error { + rlsOpts := &release.CheckOptions{ + Repository: rOpts.Repository, + ReleaseName: rOpts.Name, + AssetFiles: c.Args().Slice(), + GithubToken: rOpts.GithubToken, + } + + if rOpts.Plan != nil && rOpts.Plan.Release != nil { + rlsOpts.ReleaseName = rOpts.Plan.Release.Name + } + if rOpts.Plan != nil && rOpts.Plan.Output != nil { + rlsOpts.AssetFiles = []string{rOpts.Plan.Output.DiskImage} + } + + return release.Check(c.Context, rlsOpts) +} diff --git a/pkg/release/check.go b/pkg/release/check.go new file mode 100644 index 0000000..c4c7a6d --- /dev/null +++ b/pkg/release/check.go @@ -0,0 +1,80 @@ +package release + +import ( + "context" + "fmt" + "net/http" + "path/filepath" + "strings" + + "github.com/hashicorp/go-hclog" + "github.com/jimeh/build-emacs-for-macos/pkg/gh" + "github.com/jimeh/build-emacs-for-macos/pkg/repository" +) + +type CheckOptions struct { + // Repository is the GitHub repository to check. + Repository *repository.Repository + + // ReleaseName is the name of the GitHub Release to check. + ReleaseName string + + // AssetFiles is a list of files which must all exist in the release for + // the check to pass. + AssetFiles []string + + // GitHubToken is the OAuth token used to talk to the GitHub API. + GithubToken string +} + +// Check checks if a GitHub repository has a Release by given name, and if the +// release contains assets with given filenames. +func Check(ctx context.Context, opts *CheckOptions) error { + logger := hclog.FromContext(ctx).Named("release") + gh := gh.New(ctx, opts.GithubToken) + + repo := opts.Repository + + release, resp, err := gh.Repositories.GetReleaseByTag( + ctx, repo.Owner(), repo.Name(), opts.ReleaseName, + ) + if err != nil { + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("release %s does not exist", opts.ReleaseName) + } + + return err + } + + logger.Info("release exists", "release", opts.ReleaseName) + + missingMap := map[string]bool{} + for _, filename := range opts.AssetFiles { + filename = filepath.Base(filename) + missingMap[filename] = true + for _, a := range release.Assets { + if a.GetName() == filename { + logger.Info("asset exists", "filename", filename) + delete(missingMap, filename) + + break + } + } + } + + if len(missingMap) == 0 { + return nil + } + + var missing []string + for f := range missingMap { + missing = append(missing, f) + } + + logger.Error("missing assets", "filenames", missing) + + return fmt.Errorf( + "release %s is missing assets:\n- %s", + opts.ReleaseName, strings.Join(missing, "\n-"), + ) +} From 72ca9ce2b64505a8bbc50b3139c0f84fb24813fd Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Mon, 14 Jun 2021 01:24:56 +0100 Subject: [PATCH 09/10] feat(release): add release publish command --- pkg/cli/release.go | 84 ++++++++++++++ pkg/release/publish.go | 242 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 pkg/release/publish.go diff --git a/pkg/cli/release.go b/pkg/cli/release.go index 2c48b73..7b01074 100644 --- a/pkg/cli/release.go +++ b/pkg/cli/release.go @@ -1,7 +1,9 @@ package cli import ( + "fmt" "os" + "path/filepath" "github.com/jimeh/build-emacs-for-macos/pkg/plan" "github.com/jimeh/build-emacs-for-macos/pkg/release" @@ -57,6 +59,7 @@ func releaseCmd() *cli2.Command { }, Subcommands: []*cli2.Command{ releaseCheckCmd(), + releasePublishCmd(), }, } } @@ -122,3 +125,84 @@ func releaseCheckAction( return release.Check(c.Context, rlsOpts) } + +func releasePublishCmd() *cli2.Command { + return &cli2.Command{ + Name: "publish", + Usage: "publish a GitHub release with specified asset " + + "files", + ArgsUsage: "[ ...]", + Flags: []cli2.Flag{ + &cli2.StringFlag{ + Name: "sha", + Aliases: []string{"s"}, + Usage: "git SHA to create release on", + EnvVars: []string{"GITHUB_SHA"}, + }, + &cli2.StringFlag{ + Name: "type", + Aliases: []string{"t"}, + Usage: "release type, must be normal, prerelease, or draft", + Value: "normal", + }, + &cli2.StringFlag{ + Name: "title", + Usage: "release title, will use release name if not " + + "specified", + Value: "", + }, + }, + Action: releaseActionWrapper(releasePublishAction), + } +} + +func releasePublishAction( + c *cli2.Context, + opts *Options, + rOpts *releaseOptions, +) error { + rlsOpts := &release.PublishOptions{ + Repository: rOpts.Repository, + CommitRef: c.String("release-sha"), + ReleaseName: rOpts.Name, + ReleaseTitle: c.String("title"), + AssetFiles: c.Args().Slice(), + GithubToken: rOpts.GithubToken, + } + + rlsType := c.String("type") + switch rlsType { + case "draft": + rlsOpts.ReleaseType = release.Draft + case "prerelease": + rlsOpts.ReleaseType = release.Prerelease + case "normal": + rlsOpts.ReleaseType = release.Normal + default: + return fmt.Errorf("invalid --type \"%s\"", rlsType) + } + + if rOpts.Plan != nil { + if rOpts.Plan.Release != nil { + rlsOpts.ReleaseName = rOpts.Plan.Release.Name + rlsOpts.ReleaseTitle = rOpts.Plan.Release.Title + + if rOpts.Plan.Release.Draft { + rlsOpts.ReleaseType = release.Draft + } else if rOpts.Plan.Release.Prerelease { + rlsOpts.ReleaseType = release.Prerelease + } + } + + if rOpts.Plan.Output != nil { + rlsOpts.AssetFiles = []string{ + filepath.Join( + rOpts.Plan.Output.Directory, + rOpts.Plan.Output.DiskImage, + ), + } + } + } + + return release.Publish(c.Context, rlsOpts) +} diff --git a/pkg/release/publish.go b/pkg/release/publish.go new file mode 100644 index 0000000..d96f675 --- /dev/null +++ b/pkg/release/publish.go @@ -0,0 +1,242 @@ +package release + +import ( + "context" + "fmt" + "net/http" + "os" + "path/filepath" + + "github.com/google/go-github/v35/github" + "github.com/hashicorp/go-hclog" + "github.com/jimeh/build-emacs-for-macos/pkg/gh" + "github.com/jimeh/build-emacs-for-macos/pkg/repository" +) + +type releaseType int + +// Release type constants +const ( + Normal releaseType = iota + Draft + Prerelease +) + +type PublishOptions struct { + // Repository is the GitHub repository to publish the release on. + Repository *repository.Repository + + // CommitRef is the git commit ref to create the release tag on. + CommitRef string + + // ReleaseName is the name of the git tag to create the release on. + ReleaseName string + + // ReleaseTitle is the title of the release, if not specified ReleaseName + // will be used. + ReleaseTitle string + + // ReleaseType is the type of release to create (normal, prerelease, or + // draft) + ReleaseType releaseType + + // AssetFiles is a list of files which must all exist in the release for + // the check to pass. + AssetFiles []string + + // GitHubToken is the OAuth token used to talk to the GitHub API. + GithubToken string +} + +//nolint:funlen,gocyclo +// Publish creates and publishes a GitHub release. +func Publish(ctx context.Context, opts *PublishOptions) error { + logger := hclog.FromContext(ctx).Named("release") + gh := gh.New(ctx, opts.GithubToken) + + files, err := publishFileList(opts.AssetFiles) + if err != nil { + return err + } + + tagName := opts.ReleaseName + name := opts.ReleaseTitle + if name == "" { + name = tagName + } + + prerelease := opts.ReleaseType == Prerelease + draft := opts.ReleaseType == Draft + + logger.Info("checking release", "tag", tagName) + release, resp, err := gh.Repositories.GetReleaseByTag( + ctx, opts.Repository.Owner(), opts.Repository.Name(), tagName, + ) + if err != nil { + if resp.StatusCode != http.StatusNotFound { + return err + } + + logger.Info("creating release", "tag", tagName, "name", name) + + release, _, err = gh.Repositories.CreateRelease( + ctx, opts.Repository.Owner(), opts.Repository.Name(), + &github.RepositoryRelease{ + Name: &name, + TagName: &tagName, + TargetCommitish: &opts.CommitRef, + Prerelease: boolPtr(false), + Draft: boolPtr(true), + }, + ) + if err != nil { + return err + } + } + + for _, fileName := range files { + fileIO, err2 := os.Open(fileName) + if err2 != nil { + return err2 + } + defer fileIO.Close() + + fileInfo, err2 := fileIO.Stat() + if err2 != nil { + return err2 + } + + fileBaseName := filepath.Base(fileName) + assetExists := false + + for _, a := range release.Assets { + if a.GetName() != fileBaseName { + continue + } + + if a.GetSize() == int(fileInfo.Size()) { + logger.Info("asset exists with correct size", + "file", fileBaseName, + "local_size", byteCountIEC(fileInfo.Size()), + "remote_size", byteCountIEC(int64(a.GetSize())), + ) + assetExists = true + } else { + _, err = gh.Repositories.DeleteReleaseAsset( + ctx, opts.Repository.Owner(), opts.Repository.Name(), + a.GetID(), + ) + if err != nil { + return err + } + logger.Info( + "deleted asset with wrong size", "file", fileBaseName, + ) + } + } + + if !assetExists { + logger.Info("uploading asset", + "file", fileBaseName, + "size", byteCountIEC(fileInfo.Size()), + ) + _, _, err2 = gh.Repositories.UploadReleaseAsset( + ctx, opts.Repository.Owner(), opts.Repository.Name(), + release.GetID(), + &github.UploadOptions{Name: fileBaseName}, + fileIO, + ) + if err2 != nil { + return err2 + } + } + } + + changed := false + if release.GetName() != name { + release.Name = &name + changed = true + } + + if release.GetDraft() != draft { + release.Draft = &draft + changed = true + } + + if !draft && release.GetPrerelease() != prerelease { + release.Prerelease = &prerelease + changed = true + } + + if changed { + release, _, err = gh.Repositories.EditRelease( + ctx, opts.Repository.Owner(), opts.Repository.Name(), + release.GetID(), release, + ) + if err != nil { + return err + } + } + + logger.Info("release created", "url", release.GetHTMLURL()) + + return nil +} + +func publishFileList(files []string) ([]string, error) { + var output []string + for _, file := range files { + var err error + file, err = filepath.Abs(file) + if err != nil { + return nil, err + } + + stat, err := os.Stat(file) + if err != nil { + return nil, err + } + if !stat.Mode().IsRegular() { + return nil, fmt.Errorf("\"%s\" is not a file", file) + } + + output = append(output, file) + sumFile := file + ".sha256" + + _, err = os.Stat(sumFile) + fmt.Printf("err: %+v\n", err) + if err != nil { + if os.IsNotExist(err) { + continue + } + + return nil, err + } + output = append(output, sumFile) + } + + return output, nil +} + +func byteCountIEC(b int64) string { + const unit = 1024 + if b < unit { + if b == 1 { + return fmt.Sprintf("%d byte", b) + } + + return fmt.Sprintf("%d bytes", b) + } + div, exp := int64(unit), 0 + for n := b / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + + return fmt.Sprintf("%.1f %ciB", + float64(b)/float64(div), "KMGTPE"[exp]) +} + +func boolPtr(v bool) *bool { + return &v +} From 87d2d67575f470883ab9869593e3acf463f93d99 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sun, 20 Jun 2021 19:00:47 +0100 Subject: [PATCH 10/10] chore(makefile): add bootstrap targets for normal use and CI environments --- Brewfile.ci | 3 +++ Makefile | 17 +++++++++++++++++ requirements-ci.txt | 1 + 3 files changed, 21 insertions(+) create mode 100644 Brewfile.ci create mode 100644 requirements-ci.txt diff --git a/Brewfile.ci b/Brewfile.ci new file mode 100644 index 0000000..638e9f6 --- /dev/null +++ b/Brewfile.ci @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +brew 'python' diff --git a/Makefile b/Makefile index dfb3a8a..a3351b1 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +PIP := $(shell command -v pip3 || command -v pip) SOURCES := $(shell \ find * \ -not -path 'sources/*' \ @@ -40,6 +41,22 @@ SHELL := env \ # Default target .DEFAULT_GOAL := build +# +# Bootstrap +# + +bootstrap: bootstrap-brew +bootstrap-ci: bootstrap-brew bootstrap-brew-ci bootstrap-pip + +bootstrap-brew: + brew bundle + +bootstrap-brew-ci: + brew bundle --file Brewfile.ci + +bootstrap-pip: + $(PIP) install -r requirements-ci.txt + # # Tools # diff --git a/requirements-ci.txt b/requirements-ci.txt new file mode 100644 index 0000000..18ee57f --- /dev/null +++ b/requirements-ci.txt @@ -0,0 +1 @@ +dmgbuild