Compare commits

...

37 Commits

Author SHA1 Message Date
f1bf1d93b8 chore(release): 0.6.24 2021-11-24 21:42:52 +00:00
8a467b0d43 fix(embedding): embedding GCC fails when paths do not require sanitizing
It seems homebrew bottle of GCC for macOS Monterey (12.0) have changed their
directory structure slightly, which caused an issue were we were trying
to rename a specific directory to the same name it already had.

This behavior is still required as it looks like GCC on macOS
Catalina (10.15), the GCC homebrew bottle still uses the old directory
structure.
2021-11-24 21:39:03 +00:00
9c29f721b4 chore(release): 0.6.23 2021-11-10 22:19:28 +00:00
4ac71ddf39 docs(readme): update usage section with latest help text 2021-11-10 22:19:06 +00:00
d338c136db fix(build): do not re-link eln files by default
Relinking is currently failing for some of the *.eln files. See #60 for
details of the error.

Long-term plan is to investigate native-comp's compilation options to
hopefully resolve this issue.
2021-11-10 22:11:13 +00:00
d054a17fc7 chore(release): 0.6.22 2021-11-10 01:56:19 +00:00
4030ceb9ca feat(patch): add support for posix-spawn patch from emacs-plus 2021-11-10 01:55:38 +00:00
ad1a7dd62c chore(release): 0.6.21 2021-10-27 21:45:43 +01:00
665e6addec Merge pull request #59 from jimeh/improve-native-comp-patch 2021-10-27 21:42:05 +01:00
7f2aba0e4e chore(builder): add hidden sign-files command for testing purposes
Useful when needing to sign singular files with same ease of signing a
Emacs.app bundle.
2021-10-27 21:38:29 +01:00
be326b22aa refactor(native-comp): improve native-comp env setup patch
Instead of patching emacs sources before building Emacs, we can use
site-start.el instead for a much cleaner way of setting LIBRARY_PATH
before the user config is loaded.
2021-10-27 21:38:29 +01:00
ef4f2ad930 refactor: use site-start.el instead of abusing subdirs.el
Set source-directory in site-start.el instead of subdirs.el which we
were basically abusing to execute Elisp before the user config is
loaded.
2021-10-27 21:38:28 +01:00
2293c87fc9 refactor(build): turn add_cli_helper function into a embedder class 2021-10-27 03:12:30 +01:00
97178bf77a chore(release): 0.6.20 2021-10-23 20:35:09 +01:00
591c39e629 fix(notarization): explicitly only copy *.c and *.h C source files
Previously we just copies the whole "src" directory from the workdir, it
turns out it has some binary files after a successful build, which
caused Apple's notarization process to fail.

As we actually only care about the *.c and *.h files from the "src"
directory, let's explicitly only copy those files.
2021-10-23 20:32:13 +01:00
d6c99f8c60 chore(release): 0.6.19 2021-10-23 17:26:50 +01:00
bcbd01778d fix(patch): resolve emacs-29 symlink patches to their real URL
Annoyingly, when downloading raw files from GitHub, symlinks do not
return the content of the symlink target, but instead it simply returns
the symlink target path (../emacs-28/fix-window-role.patch).

Hence we have to check the patch file content, and if it contains only a
single line of text, we assume it's a symlink, and resolve it relative
to the original download URL.
2021-10-23 17:24:45 +01:00
5602475542 chore(release): 0.6.18 2021-10-23 16:20:44 +01:00
67b8c5f397 feat(docs): embed C source files and set source-directory accordingly
This enables the original C source to be linked to when describing
entities which are written in C.
2021-10-23 16:18:05 +01:00
4dad5812fa fix(patches): correctly use emacs 28.x and 29.x patches
The master branch is now Emacs 29.x, and Emacs 28.x lives on the
"emacs-28" release branch.
2021-10-23 16:15:39 +01:00
65bdff0b6d chore(release): 0.6.17 2021-10-10 22:42:01 +01:00
a956dc1b42 feat(release): tweak GitHub release description 2021-10-10 22:41:26 +01:00
af23b63518 chore(release): 0.6.16 2021-10-10 18:44:41 +01:00
9c20f77fe3 Merge pull request #58 from jimeh/release-improvements 2021-10-10 18:42:37 +01:00
2e2f9bc98a feat(build): handle macOS Big Sur and later version number 2021-10-10 18:25:38 +01:00
d63cd545aa feat(cask): make cask template helpers more flexible
Helpers available in cask templates can now accept one or more strings
as input, and first asset filename that matches all given strings is
returned.
2021-10-10 18:25:38 +01:00
1bbfe5d3ea feat(plan): allow build plan to be output as YAML or JSON 2021-10-10 18:25:37 +01:00
b4c5184cef fix(release): publish arguments are not handled as asset files to upload 2021-10-10 18:25:37 +01:00
e7a991ef92 feat(release): force-replace existing asset files by default
The file-size check is obviously not a very reliable way to determine if
the local and remote files are different. Hence we now default to always
uploading all given asset files, replacing any existing ones with the
same file name.

The size check logic is still available via the --asset-size-check flag.
2021-10-10 18:25:37 +01:00
7118ed8560 feat(release): add description to GitHub Releases
The description includes links to the Emacs source repo used, the git
ref, commit, tarball download URL, and build log (GitHub Actions Run).
2021-10-10 18:25:36 +01:00
a71cbda511 chore(release): remove default release repository value
This should be explicitly provided via environment variable of command
line flag.
2021-10-10 18:25:36 +01:00
4c0eb37353 chore(debug): remove left-over debug print statement 2021-10-10 18:25:36 +01:00
b81e101ca7 style(lint): Renamed unused function arguments to _ 2021-10-10 18:25:35 +01:00
c760ffa25e Merge pull request #55 from puzza007/patch-1
Fix typo in log message
2021-08-30 10:11:58 +01:00
Paul Oliver
931e6ddf9e Fix typo in log message 2021-08-26 16:00:12 +12:00
f17f485b9f chore(release): 0.6.15 2021-08-05 02:38:15 +01:00
3622df550c fix(build): another --relink-eln-files flag fix
I probably should not be doing these kind of changes after midnight
as I get too lazy to test it as it takes like 20 minutes to do a build
locally :P
2021-08-05 02:37:01 +01:00
20 changed files with 669 additions and 222 deletions

View File

@@ -75,6 +75,9 @@ issues:
- source: "`json:"
linters:
- lll
- source: "`yaml:"
linters:
- lll
run:
skip-dirs:

View File

@@ -2,6 +2,85 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.6.24](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.23...v0.6.24) (2021-11-24)
### Bug Fixes
* **embedding:** embedding GCC fails when paths do not require sanitizing ([8a467b0](https://github.com/jimeh/build-emacs-for-macos/commit/8a467b0d43140f6956d53c27e2319ae1b572868c))
### [0.6.23](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.22...v0.6.23) (2021-11-10)
### Bug Fixes
* **build:** do not re-link eln files by default ([d338c13](https://github.com/jimeh/build-emacs-for-macos/commit/d338c136db8acc4378154cf66ed7db5462787602)), closes [#60](https://github.com/jimeh/build-emacs-for-macos/issues/60)
### [0.6.22](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.21...v0.6.22) (2021-11-10)
### Features
* **patch:** add support for posix-spawn patch from emacs-plus ([4030ceb](https://github.com/jimeh/build-emacs-for-macos/commit/4030ceb9cab6749af3c28161ac97caec90a8aed0))
### [0.6.21](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.20...v0.6.21) (2021-10-27)
### [0.6.20](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.19...v0.6.20) (2021-10-23)
### Bug Fixes
* **notarization:** explicitly only copy *.c and *.h C source files ([591c39e](https://github.com/jimeh/build-emacs-for-macos/commit/591c39e629c9556adcf296cd5c15dd0b17c4d986))
### [0.6.19](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.18...v0.6.19) (2021-10-23)
### Bug Fixes
* **patch:** resolve emacs-29 symlink patches to their real URL ([bcbd017](https://github.com/jimeh/build-emacs-for-macos/commit/bcbd01778d416b99205c51f348a543489889f66d))
### [0.6.18](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.17...v0.6.18) (2021-10-23)
### Features
* **docs:** embed C source files and set source-directory accordingly ([67b8c5f](https://github.com/jimeh/build-emacs-for-macos/commit/67b8c5f3974e178e31519846d46af82d9770ad6e))
### Bug Fixes
* **patches:** correctly use emacs 28.x and 29.x patches ([4dad581](https://github.com/jimeh/build-emacs-for-macos/commit/4dad5812fa2b67adc7262a778829013995a904bc))
### [0.6.17](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.16...v0.6.17) (2021-10-10)
### Features
* **release:** tweak GitHub release description ([a956dc1](https://github.com/jimeh/build-emacs-for-macos/commit/a956dc1b42b2648e2663f5b48c72d7428fe75f19))
### [0.6.16](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.15...v0.6.16) (2021-10-10)
### Features
* **build:** handle macOS Big Sur and later version number ([2e2f9bc](https://github.com/jimeh/build-emacs-for-macos/commit/2e2f9bc98acdc972a22add3d1015bd80cad20b41))
* **cask:** make cask template helpers more flexible ([d63cd54](https://github.com/jimeh/build-emacs-for-macos/commit/d63cd545aab3a35e0cbbbcabd862525acbc414b8))
* **plan:** allow build plan to be output as YAML or JSON ([1bbfe5d](https://github.com/jimeh/build-emacs-for-macos/commit/1bbfe5d3ea810215b417e5b80d2902f03d68f366))
* **release:** add description to GitHub Releases ([7118ed8](https://github.com/jimeh/build-emacs-for-macos/commit/7118ed856053de06ddcdfba2a2d6fa40f58c17ab))
* **release:** force-replace existing asset files by default ([e7a991e](https://github.com/jimeh/build-emacs-for-macos/commit/e7a991ef92a5c546106a8badaf9c60247a1397b5))
### Bug Fixes
* **release:** publish arguments are not handled as asset files to upload ([b4c5184](https://github.com/jimeh/build-emacs-for-macos/commit/b4c5184cefe43fdc54b1ad5c8a1970f104137644))
### [0.6.15](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.14...v0.6.15) (2021-08-05)
### Bug Fixes
* **build:** another --relink-eln-files flag fix ([3622df5](https://github.com/jimeh/build-emacs-for-macos/commit/3622df550c72fc9da70235005239b278b5822cf6))
### [0.6.14](https://github.com/jimeh/build-emacs-for-macos/compare/v0.6.13...v0.6.14) (2021-08-05)

View File

@@ -81,8 +81,10 @@ Options:
--[no-]native-comp Enable/disable native-comp (default: enabled if supported)
--[no-]native-march Enable/disable -march=native CFLAG(default: disabled)
--[no-]native-full-aot Enable/disable NATIVE_FULL_AOT / Ahead of Time compilation (default: disabled)
--[no-]relink-eln-files Enable/disable re-linking shared libraries in bundled *.eln files (default: disabled)
--[no-]rsvg Enable/disable SVG image support via librsvg (default: enabled)
--no-titlebar Apply no-titlebar patch (default: disabled)
--posix-spawn Apply posix-spawn patch (default: disabled)
--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
@@ -90,7 +92,8 @@ Options:
--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)
--[no-]archive-keep-build-dir
Enable/disable keeping source folder for archive (default: disabled)
--plan FILE Follow given plan file, instead of using given git ref/sha
```

View File

@@ -53,7 +53,7 @@ class OSVersion
end
def to_s
@to_s ||= "#{major}.#{minor}"
@to_s ||= major >= 11 ? major.to_s : "#{major}.#{minor}"
end
def major
@@ -105,8 +105,9 @@ class Build
build_dir, app = create_build_dir(app)
handle_native_lisp(app)
add_cli_helper(app)
CLIHelperEmbedder.new(app).embed
CSourcesEmbedder.new(app, @source_dir).embed
LibEmbedder.new(app, brew_dir, extra_libs, options[:relink_eln]).embed
GccLibEmbedder.new(app, gcc_info).embed if options[:native_comp]
@@ -285,8 +286,6 @@ class Build
verify_native_comp
gcc_info.verify_libgccjit
apply_native_comp_env_setup_patch(source)
ENV['CFLAGS'] = [
"-I#{File.join(gcc_info.root_dir, 'include')}",
"-I#{File.join(gcc_info.libgccjit_root_dir, 'include')}",
@@ -505,18 +504,6 @@ class Build
end
end
def add_cli_helper(app)
source = File.join(__dir__, 'helper', 'emacs-cli.bash')
target = File.join(app, 'Contents', 'MacOS', 'bin', 'emacs')
dir = File.dirname(target)
info "Adding \"emacs\" CLI helper to #{dir}"
FileUtils.mkdir_p(dir)
FileUtils.cp(source, target)
FileUtils.chmod('+w', target)
end
def build_name
return @build_name if @build_name
return @build_name = options[:build_name] if options[:build_name]
@@ -551,7 +538,7 @@ class Build
system('tar', '-cjf', archive_filename, build)
if options[:archive_keep] == false
info "Removeing \"#{build}\" directory from #{parent_dir}"
info "Removing \"#{build}\" directory from #{parent_dir}"
FileUtils.rm_rf(build_dir)
end
end
@@ -618,21 +605,6 @@ class Build
system(*args) || err("Exit code: #{$CHILD_STATUS.exitstatus}")
end
def apply_native_comp_env_setup_patch(source)
term = 'native-compile-setup-environment-variables'
file = 'lisp/emacs-lisp/comp.el'
return if `grep '#{term}' '#{file}'`.strip.size.positive?
template = File.read(
File.join(__dir__, 'patches/native-comp-env-setup.diff.erb')
)
patch = ERB.new(template).result(gcc_info.get_binding)
patch_file = File.join(source, 'macos_patches/native-comp-env-setup.diff')
File.write(patch_file, patch)
apply_patch({ file: patch_file }, source)
end
def effective_version
@effective_version ||= begin
case ref
@@ -640,8 +612,10 @@ class Build
'emacs-26'
when /^emacs-27.*/
'emacs-27'
else
when /^emacs-28.*/
'emacs-28'
else
'emacs-29'
end
end
end
@@ -649,14 +623,14 @@ class Build
def patches(opts = {})
p = []
if %w[emacs-26 emacs-27 emacs-28].include?(effective_version)
if %w[emacs-26 emacs-27 emacs-28 emacs-29].include?(effective_version)
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
"patches/#{effective_version}/fix-window-role.patch"
}
end
if %w[emacs-27 emacs-28].include?(effective_version)
if %w[emacs-27 emacs-28 emacs-29].include?(effective_version)
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
"patches/#{effective_version}/system-appearance.patch"
@@ -677,6 +651,15 @@ class Build
end
end
if %w[emacs-28 emacs-29].include?(effective_version)
if options[:posix_spawn]
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
"patches/#{effective_version}/posix-spawn.patch"
}
end
end
if effective_version == 'emacs-27'
p << {
url: 'https://github.com/d12frosted/homebrew-emacs-plus/raw/master/' \
@@ -714,7 +697,14 @@ class Build
info "Downloading patch: #{patch[:url]}"
run_cmd('curl', '-L#', patch[:url], '-o', patch_file)
apply_patch({ file: patch_file }, target)
real_patch_url = detect_github_symlink_patch(patch[:url], patch_file)
if real_patch_url
FileUtils.rm(patch_file)
apply_patch({ url: real_patch_url }, target)
else
apply_patch({ file: patch_file }, target)
end
elsif patch[:replace]
err 'Patch replace input error' unless patch[:replace].size == 3
@@ -732,6 +722,30 @@ class Build
f.close
end
end
# When downloading raw files from GitHub, if the target file is a symlink, it
# will return the actual target path of the symlink instead of the content of
# the target file. Hence we have to check if the patch file we have downloaded
# contains one and only one line, and if so, assume it's a symlink.
def detect_github_symlink_patch(original_url, patch_file)
lines = []
# read first two lines
File.open(patch_file) do |f|
lines << f.gets
lines << f.gets
end
# if the file contains more than one line of text, it's not a symlink.
return unless lines[1].nil?
symlink_target = lines[0].strip
# Assume patch file content is something along the lines of
# "../emacs-28/fix-window-role.patch", hence we resolve it relative to the
# original url.
info "patch is symlink to #{symlink_target}"
URI.join(original_url, symlink_target).to_s
end
end
class AbstractEmbedder
@@ -753,20 +767,84 @@ class AbstractEmbedder
File.join(invocation_dir, 'Emacs')
end
def bin_dir
File.join(invocation_dir, 'bin')
end
def lib_dir
File.join(invocation_dir, 'lib')
end
def resources_dir
File.join(app, 'Contents', 'Resources')
end
end
class CLIHelperEmbedder < AbstractEmbedder
def embed
source = File.join(__dir__, 'helper', 'emacs-cli.bash')
target = File.join(bin_dir, 'emacs')
dir = File.dirname(target)
info "Adding \"emacs\" CLI helper to #{dir}"
FileUtils.mkdir_p(dir)
FileUtils.cp(source, target)
FileUtils.chmod('+w', target)
end
end
class CSourcesEmbedder < AbstractEmbedder
PATH_PATCH = <<~ELISP
;; Allow Emacs to find bundled C sources.
(setq source-directory (expand-file-name ".."))
ELISP
attr_reader :source_dir
def initialize(app, source_dir)
super(app)
@source_dir = source_dir
end
def embed
info 'Embedding C source files into Emacs.app for documentation purposes'
src_dir = File.join(source_dir, 'src')
Dir[File.join(src_dir, '**', '*.{c,h}')].each do |f|
rel = f[src_dir.size + 1..-1]
target = File.join(resources_dir, 'src', rel)
FileUtils.mkdir_p(File.dirname(target))
FileUtils.cp(f, target)
end
return if File.exist?(site_start_el_file) &&
File.read(site_start_el_file).include?(PATH_PATCH)
File.open(site_start_el_file, 'a') do |f|
f.puts("\n#{PATH_PATCH}")
end
end
private
def site_start_el_file
@site_start_el_file ||= File.join(resources_dir, 'lisp', 'site-start.el')
end
end
class LibEmbedder < AbstractEmbedder
attr_reader :lib_source
attr_reader :extra_libs
attr_reader :embed_eln_files
def initialize(app, lib_source, extra_libs = [], embed_eln_files = true)
super(app)
@lib_source = lib_source
@extra_libs = extra_libs
@embed_eln_files = embed_eln_files
end
def embed
@@ -888,11 +966,48 @@ class GccLibEmbedder < AbstractEmbedder
FileUtils.cp_r(source_dir, target_dir)
FileUtils.rm(Dir[File.join(target_dir, '**', '.DS_Store')], force: true)
FileUtils.chmod_R('u+w', target_dir)
FileUtils.mv(source_darwin_dir, target_darwin_dir)
if source_darwin_dir != target_darwin_dir
FileUtils.mv(source_darwin_dir, target_darwin_dir)
end
env_setup = ERB.new(NATIVE_COMP_ENV_VAR_TPL).result(gcc_info.get_binding)
return if File.exist?(site_start_el_file) &&
File.read(site_start_el_file).include?(env_setup)
File.open(site_start_el_file, 'a') do |f|
f.puts("\n#{env_setup}")
end
end
private
NATIVE_COMP_ENV_VAR_TPL = <<~ELISP
;; Set LIBRARY_PATH to point at bundled GCC and Xcode Command Line Tools to
;; ensure native-comp works.
(when (and (eq system-type 'darwin)
(string-match-p "\\.app\\/Contents\\/MacOS\\/?$"
invocation-directory))
(let* ((library-path-env (getenv "LIBRARY_PATH"))
(devtools-dir
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib")
(gcc-dir (expand-file-name
"<%= app_bundle_relative_lib_dir %>"
invocation-directory))
(darwin-dir (expand-file-name
"<%= app_bundle_relative_darwin_lib_dir %>"
invocation-directory))
(lib-paths (list)))
(if library-path-env
(push library-path-env lib-paths))
(if (file-directory-p devtools-dir)
(push devtools-dir lib-paths))
(push darwin-dir lib-paths)
(push gcc-dir lib-paths)
(setenv "LIBRARY_PATH" (mapconcat 'identity lib-paths ":"))))
ELISP
def embedded?
Dir[File.join(target_dir, 'libgcc*')].any?
end
@@ -916,6 +1031,10 @@ class GccLibEmbedder < AbstractEmbedder
def relative_dir(path, root)
Pathname.new(path).relative_path_from(Pathname.new(root)).to_s
end
def site_start_el_file
@site_start_el_file ||= File.join(resources_dir, 'lisp', 'site-start.el')
end
end
class GccInfo
@@ -1036,6 +1155,7 @@ if __FILE__ == $PROGRAM_NAME
cli_options = {
work_dir: File.expand_path(__dir__),
native_full_aot: false,
relink_eln: false,
native_march: false,
parallel: Etc.nprocessors,
rsvg: true,
@@ -1095,7 +1215,7 @@ if __FILE__ == $PROGRAM_NAME
opts.on('--[no-]relink-eln-files',
'Enable/disable re-linking shared libraries in bundled *.eln ' \
'files (default: enabled)') do |v|
'files (default: disabled)') do |v|
cli_options[:relink_eln] = v
end
@@ -1109,6 +1229,10 @@ if __FILE__ == $PROGRAM_NAME
cli_options[:no_titlebar] = true
end
opts.on('--posix-spawn', 'Apply posix-spawn patch (default: disabled)') do
cli_options[:posix_spawn] = true
end
opts.on('--no-frame-refocus',
'Apply no-frame-refocus patch (default: disabled)') do
cli_options[:no_frame_refocus] = true

View File

@@ -1,57 +0,0 @@
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 638d4b274c..2599211936 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -4224,6 +4224,52 @@ native-compile-async
(let ((load (not (not load))))
(native--compile-async files recursively load selector)))
+;;;###autoload
+(defun native-compile-setup-environment-variables (&rest _args)
+ "Ensure LIBRARY_PATH is set correctly when libgccjit is bundled."
+ (when (and (eq system-type 'darwin)
+ (string-match-p "\.app\/Contents\/MacOS\/?$"
+ invocation-directory))
+ (let* ((library-path-env (getenv "LIBRARY_PATH"))
+ (devtools-dir
+ "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib")
+ (gcc-dir (expand-file-name
+ "<%= app_bundle_relative_lib_dir %>"
+ invocation-directory))
+ (darwin-dir (expand-file-name
+ "<%= app_bundle_relative_darwin_lib_dir %>"
+ invocation-directory))
+ (lib-paths (list)))
+
+ (if library-path-env
+ (push library-path-env lib-paths))
+ (if (file-directory-p devtools-dir)
+ (push devtools-dir lib-paths))
+ (push darwin-dir lib-paths)
+ (push gcc-dir lib-paths)
+
+ (setenv "LIBRARY_PATH" (mapconcat 'identity lib-paths ":"))))
+
+ ;; Remove advice, as it only needs to run once.
+ (advice-remove 'native-compile
+ 'native-compile-setup-environment-variables)
+ (advice-remove 'comp--native-compile
+ 'native-compile-setup-environment-variables)
+ (advice-remove 'native-compile-async
+ 'native-compile-setup-environment-variables)
+ (advice-remove 'native--compile-async
+ 'native-compile-setup-environment-variables))
+
+;; Ensure environment setup runs before any native compilation.
+(advice-add 'native-compile :before
+ 'native-compile-setup-environment-variables)
+(advice-add 'comp--native-compile :before
+ 'native-compile-setup-environment-variables)
+(advice-add 'native-compile-async :before
+ 'native-compile-setup-environment-variables)
+(advice-add 'native--compile-async :before
+ 'native-compile-setup-environment-variables)
+
(provide 'comp)
;; LocalWords: limplified limplified limplification limplify Limple LIMPLE libgccjit elc eln

View File

@@ -11,9 +11,11 @@ type ReleaseInfo struct {
Assets map[string]*ReleaseAsset
}
func (s *ReleaseInfo) Asset(nameMatch string) *ReleaseAsset {
if a, ok := s.Assets[nameMatch]; ok {
return a
func (s *ReleaseInfo) Asset(needles ...string) *ReleaseAsset {
if len(needles) == 1 {
if a, ok := s.Assets[needles[0]]; ok {
return a
}
}
// Dirty and inefficient way to ensure assets are searched in a predictable
@@ -27,16 +29,20 @@ func (s *ReleaseInfo) Asset(nameMatch string) *ReleaseAsset {
})
for _, a := range assets {
if strings.Contains(a.Filename, nameMatch) {
return a
for _, needle := range needles {
if !strings.Contains(a.Filename, needle) {
continue
}
}
return a
}
return nil
}
func (s *ReleaseInfo) DownloadURL(nameMatch string) string {
a := s.Asset(nameMatch)
func (s *ReleaseInfo) DownloadURL(needles ...string) string {
a := s.Asset(needles...)
if a == nil {
return ""
}
@@ -44,8 +50,8 @@ func (s *ReleaseInfo) DownloadURL(nameMatch string) string {
return a.DownloadURL
}
func (s *ReleaseInfo) SHA256(nameMatch string) string {
a := s.Asset(nameMatch)
func (s *ReleaseInfo) SHA256(needles ...string) string {
a := s.Asset(needles...)
if a == nil {
return ""
}

View File

@@ -112,7 +112,7 @@ func caskUpdateCmd() *cli2.Command {
func caskUpdateAction(
c *cli2.Context,
opts *Options,
_ *Options,
cOpts *caskOptions,
) error {
updateOpts := &cask.UpdateOptions{

View File

@@ -46,6 +46,7 @@ func New(version, commit, date string) *CLI {
Commands: []*cli2.Command{
planCmd(),
signCmd(),
signFilesCmd(),
notarizeCmd(),
packageCmd(),
releaseCmd(),

View File

@@ -52,7 +52,7 @@ func notarizeCmd() *cli2.Command {
}
}
func notarizeAction(c *cli2.Context, opts *Options) error {
func notarizeAction(c *cli2.Context, _ *Options) error {
options := &notarize.Options{
File: c.Args().Get(0),
BundleID: c.String("bundle-id"),

View File

@@ -1,6 +1,7 @@
package cli
import (
"fmt"
"os"
"path/filepath"
@@ -37,6 +38,12 @@ func planCmd() *cli2.Command {
Name: "sha",
Usage: "override commit SHA of specified git branch/tag",
},
&cli2.StringFlag{
Name: "format",
Aliases: []string{"f"},
Usage: "output format of build plan (yaml or json)",
Value: "yaml",
},
&cli2.StringFlag{
Name: "output",
Usage: "output filename to write plan to instead of printing " +
@@ -102,7 +109,18 @@ func planAction(c *cli2.Context, opts *Options) error {
return err
}
planYAML, err := p.YAML()
format := c.String("format")
var plan string
switch format {
case "yaml", "yml":
format = "yaml"
plan, err = p.YAML()
case "json":
format = "json"
plan, err = p.JSON()
default:
err = fmt.Errorf("--format must be yaml or json")
}
if err != nil {
return err
}
@@ -111,7 +129,7 @@ func planAction(c *cli2.Context, opts *Options) error {
out = os.Stdout
if f := c.String("output"); f != "" {
logger.Info("writing plan", "file", f)
logger.Debug("content", "yaml", planYAML)
logger.Debug("content", format, plan)
out, err = os.Create(f)
if err != nil {
return err
@@ -119,7 +137,7 @@ func planAction(c *cli2.Context, opts *Options) error {
defer out.Close()
}
_, err = out.WriteString(planYAML)
_, err = out.WriteString(plan)
if err != nil {
return err
}

View File

@@ -43,7 +43,7 @@ func releaseCmd() *cli2.Command {
Usage: "owner/name of GitHub repo to check for release, " +
"ignored if a plan is provided",
EnvVars: []string{"GITHUB_REPOSITORY"},
Value: "jimeh/emacs-builds",
Value: "",
},
&cli2.StringFlag{
Name: "name",
@@ -108,7 +108,7 @@ func releaseCheckCmd() *cli2.Command {
func releaseCheckAction(
c *cli2.Context,
opts *Options,
_ *Options,
rOpts *releaseOptions,
) error {
rlsOpts := &release.CheckOptions{
@@ -153,6 +153,12 @@ func releasePublishCmd() *cli2.Command {
"specified",
Value: "",
},
&cli2.BoolFlag{
Name: "asset-size-check",
Usage: "Do not replace existing asset files if local and " +
"remote file sizes match.",
Value: false,
},
},
Action: releaseActionWrapper(releasePublishAction),
}
@@ -160,16 +166,17 @@ func releasePublishCmd() *cli2.Command {
func releasePublishAction(
c *cli2.Context,
opts *Options,
_ *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,
Repository: rOpts.Repository,
CommitRef: c.String("release-sha"),
ReleaseName: rOpts.Name,
ReleaseTitle: c.String("title"),
AssetFiles: c.Args().Slice(),
AssetSizeCheck: c.Bool("asset-size-check"),
GithubToken: rOpts.GithubToken,
}
rlsType := c.String("type")
@@ -184,7 +191,13 @@ func releasePublishAction(
return fmt.Errorf("invalid --type \"%s\"", rlsType)
}
if c.Args().Len() > 0 {
rlsOpts.AssetFiles = c.Args().Slice()
}
if rOpts.Plan != nil {
rlsOpts.Source = rOpts.Plan.Source
if rOpts.Plan.Release != nil {
rlsOpts.ReleaseName = rOpts.Plan.Release.Name
rlsOpts.ReleaseTitle = rOpts.Plan.Release.Title
@@ -196,7 +209,8 @@ func releasePublishAction(
}
}
if rOpts.Plan.Output != nil {
// Set asset files based on plan if no file arguments were given.
if len(rlsOpts.AssetFiles) == 0 && rOpts.Plan.Output != nil {
rlsOpts.AssetFiles = []string{
filepath.Join(
rOpts.Plan.Output.Directory,
@@ -235,7 +249,7 @@ func releaseBulkCmd() *cli2.Command {
func releaseBulkAction(
c *cli2.Context,
opts *Options,
_ *Options,
rOpts *releaseOptions,
) error {
bulkOpts := &release.BulkOptions{

View File

@@ -112,3 +112,49 @@ func signAction(c *cli2.Context, opts *Options) error {
return sign.Emacs(c.Context, app, signOpts)
}
func signFilesCmd() *cli2.Command {
signCmd := signCmd()
var flags []cli2.Flag
for _, f := range signCmd.Flags {
n := f.Names()
if len(n) > 0 && n[0] == "plan" {
continue
}
flags = append(flags, f)
}
return &cli2.Command{
Name: "sign-files",
Usage: "sign files with codesign",
ArgsUsage: "<file> [<file>...]",
Hidden: true,
Flags: flags,
Action: actionWrapper(signFilesAction),
}
}
func signFilesAction(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
}
return sign.Files(c.Context, c.Args().Slice(), signOpts)
}

View File

@@ -8,11 +8,11 @@ import (
)
type Commit struct {
SHA string `yaml:"sha"`
Date *time.Time `yaml:"date"`
Author string `yaml:"author"`
Committer string `yaml:"committer"`
Message string `yaml:"message"`
SHA string `yaml:"sha" json:"sha"`
Date *time.Time `yaml:"date" json:"date"`
Author string `yaml:"author" json:"author"`
Committer string `yaml:"committer" json:"committer"`
Message string `yaml:"message" json:"message"`
}
func New(rc *github.RepositoryCommit) *Commit {

View File

@@ -2,13 +2,14 @@ package osinfo
import (
"os/exec"
"strconv"
"strings"
)
type OSInfo struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Arch string `yaml:"arch"`
Name string `yaml:"name" json:"name"`
Version string `yaml:"version" json:"version"`
Arch string `yaml:"arch" json:"arch"`
}
func New() (*OSInfo, error) {
@@ -29,8 +30,17 @@ func New() (*OSInfo, error) {
}, nil
}
func (s *OSInfo) MajorMinor() string {
// DistinctVersion returns macOS version down to a distinct "major"
// version. For macOS 10.x, this will include the first two numeric parts of the
// version (10.15), while for 11.x and later, the first numeric part is enough
// (11).
func (s *OSInfo) DistinctVersion() string {
parts := strings.Split(s.Version, ".")
if n, _ := strconv.Atoi(parts[0]); n >= 11 {
return parts[0]
}
max := len(parts)
if max > 2 {
max = 2

View File

@@ -13,6 +13,7 @@ import (
"github.com/jimeh/build-emacs-for-macos/pkg/osinfo"
"github.com/jimeh/build-emacs-for-macos/pkg/release"
"github.com/jimeh/build-emacs-for-macos/pkg/repository"
"github.com/jimeh/build-emacs-for-macos/pkg/source"
)
var nonAlphaNum = regexp.MustCompile(`[^\w_-]+`)
@@ -76,7 +77,7 @@ func Create(ctx context.Context, opts *Options) (*Plan, error) {
buildName := fmt.Sprintf(
"Emacs.%s.%s.%s",
version,
sanitizeString(osInfo.Name+"-"+osInfo.MajorMinor()),
sanitizeString(osInfo.Name+"-"+osInfo.DistinctVersion()),
sanitizeString(osInfo.Arch),
)
diskImage := buildName + ".dmg"
@@ -85,11 +86,11 @@ func Create(ctx context.Context, opts *Options) (*Plan, error) {
Build: &Build{
Name: buildName,
},
Source: &Source{
Source: &source.Source{
Ref: opts.Ref,
Repository: repo,
Commit: commitInfo,
Tarball: &Tarball{
Tarball: &source.Tarball{
URL: repo.TarballURL(commitInfo.SHA),
},
},

View File

@@ -2,21 +2,21 @@ package plan
import (
"bytes"
"encoding/json"
"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"
"github.com/jimeh/build-emacs-for-macos/pkg/source"
"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"`
Build *Build `yaml:"build,omitempty" json:"build,omitempty"`
Source *source.Source `yaml:"source,omitempty" json:"source,omitempty"`
OS *osinfo.OSInfo `yaml:"os,omitempty" json:"os,omitempty"`
Release *Release `yaml:"release,omitempty" json:"release,omitempty"`
Output *Output `yaml:"output,omitempty" json:"output,omitempty"`
}
// Load attempts to loads a plan YAML from given filename.
@@ -54,29 +54,37 @@ func (s *Plan) YAML() (string, error) {
return buf.String(), nil
}
// WriteJSON writes plan in JSON format to given io.Writer.
func (s *Plan) WriteJSON(w io.Writer) error {
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
return enc.Encode(s)
}
// JSON returns plan in JSON format.
func (s *Plan) JSON() (string, error) {
var buf bytes.Buffer
err := s.WriteJSON(&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"`
Name string `yaml:"name,omitempty" json:"name,omitempty"`
}
type Release struct {
Name string `yaml:"name"`
Title string `yaml:"title,omitempty"`
Draft bool `yaml:"draft,omitempty"`
Prerelease bool `yaml:"prerelease,omitempty"`
Name string `yaml:"name" json:"name"`
Title string `yaml:"title,omitempty" json:"title,omitempty"`
Draft bool `yaml:"draft,omitempty" json:"draft,omitempty"`
Prerelease bool `yaml:"prerelease,omitempty" json:"prerelease,omitempty"`
}
type Output struct {
Directory string `yaml:"directory,omitempty"`
DiskImage string `yaml:"disk_image,omitempty"`
Directory string `yaml:"directory,omitempty" json:"directory,omitempty"`
DiskImage string `yaml:"disk_image,omitempty" json:"disk_image,omitempty"`
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/hashicorp/go-hclog"
"github.com/jimeh/build-emacs-for-macos/pkg/gh"
"github.com/jimeh/build-emacs-for-macos/pkg/repository"
"github.com/jimeh/build-emacs-for-macos/pkg/source"
)
type releaseType int
@@ -40,15 +41,26 @@ type PublishOptions struct {
// draft)
ReleaseType releaseType
// Source contains the source used to build the asset files. When set a
// release body/description text will be generated based on source commit
// details.
Source *source.Source
// AssetFiles is a list of files which must all exist in the release for
// the check to pass.
AssetFiles []string
// AssetSizeCheck causes a file size check for any existing asset files on a
// release which have the same filename as a asset we want to upload. If the
// size of the local and remote files are the same, the existing asset file
// is left in place. When this is false, given asset files will always be
// uploaded, replacing any asset files with the same filename.
AssetSizeCheck bool
// 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")
@@ -68,6 +80,16 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
prerelease := opts.ReleaseType == Prerelease
draft := opts.ReleaseType == Draft
body := ""
if opts.Source != nil {
body, err = releaseBody(opts)
if err != nil {
return err
}
logger.Debug("rendered release body", "content", body)
}
created := false
logger.Info("checking release", "tag", tagName)
release, resp, err := gh.Repositories.GetReleaseByTag(
ctx, opts.Repository.Owner(), opts.Repository.Name(), tagName,
@@ -77,6 +99,7 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
return err
}
created = true
logger.Info("creating release", "tag", tagName, "name", name)
release, _, err = gh.Repositories.CreateRelease(
@@ -87,6 +110,7 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
TargetCommitish: &opts.CommitRef,
Prerelease: boolPtr(false),
Draft: boolPtr(true),
Body: &body,
},
)
if err != nil {
@@ -94,62 +118,9 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
}
}
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
}
}
err = uploadReleaseAssets(ctx, gh, release, files, opts)
if err != nil {
return err
}
changed := false
@@ -158,6 +129,11 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
changed = true
}
if body != "" && release.GetBody() != body {
release.Body = &body
changed = true
}
if release.GetDraft() != draft {
release.Draft = &draft
changed = true
@@ -169,6 +145,7 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
}
if changed {
logger.Info("updating release attributes", "url", release.GetHTMLURL())
release, _, err = gh.Repositories.EditRelease(
ctx, opts.Repository.Owner(), opts.Repository.Name(),
release.GetID(), release,
@@ -178,13 +155,89 @@ func Publish(ctx context.Context, opts *PublishOptions) error {
}
}
logger.Info("release created", "url", release.GetHTMLURL())
if created {
logger.Info("release created", "url", release.GetHTMLURL())
} else {
logger.Info("release updated", "url", release.GetHTMLURL())
}
return nil
}
func uploadReleaseAssets(
ctx context.Context,
gh *github.Client,
release *github.RepositoryRelease,
fileNames []string,
opts *PublishOptions,
) error {
logger := hclog.FromContext(ctx).Named("release")
for _, fileName := range fileNames {
logger.Debug("processing asset", "file", filepath.Base(fileName))
fileIO, err := os.Open(fileName)
if err != nil {
return err
}
defer fileIO.Close()
fileInfo, err := fileIO.Stat()
if err != nil {
return err
}
fileBaseName := filepath.Base(fileName)
assetExists := false
for _, a := range release.Assets {
if a.GetName() != fileBaseName {
continue
}
if opts.AssetSizeCheck && 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 {
logger.Info(
"deleting existing asset", "file", fileBaseName,
)
_, err = gh.Repositories.DeleteReleaseAsset(
ctx, opts.Repository.Owner(), opts.Repository.Name(),
a.GetID(),
)
if err != nil {
return err
}
}
}
if !assetExists {
logger.Info("uploading asset",
"file", fileBaseName,
"size", byteCountIEC(fileInfo.Size()),
)
_, _, err = gh.Repositories.UploadReleaseAsset(
ctx, opts.Repository.Owner(), opts.Repository.Name(),
release.GetID(),
&github.UploadOptions{Name: fileBaseName},
fileIO,
)
if err != nil {
return err
}
}
}
return nil
}
func publishFileList(files []string) ([]string, error) {
var output []string
results := map[string]struct{}{}
for _, file := range files {
var err error
file, err = filepath.Abs(file)
@@ -200,11 +253,10 @@ func publishFileList(files []string) ([]string, error) {
return nil, fmt.Errorf("\"%s\" is not a file", file)
}
output = append(output, file)
results[file] = struct{}{}
sumFile := file + ".sha256"
_, err = os.Stat(sumFile)
fmt.Printf("err: %+v\n", err)
if err != nil {
if os.IsNotExist(err) {
continue
@@ -212,7 +264,12 @@ func publishFileList(files []string) ([]string, error) {
return nil, err
}
output = append(output, sumFile)
results[sumFile] = struct{}{}
}
var output []string
for f := range results {
output = append(output, f)
}
return output, nil

View File

@@ -0,0 +1,78 @@
package release
import (
"bytes"
"os"
"strings"
"text/template"
)
var tplFuncs = template.FuncMap{
"indent": func(n int, s string) string {
pad := strings.Repeat(" ", n)
return pad + strings.ReplaceAll(s, "\n", "\n"+pad)
},
}
var bodyTpl = template.Must(template.New("body").Funcs(tplFuncs).Parse(`
{{- $t := "` + "`" + `" -}}
### Build Details
{{ with .SourceURL -}}
- Source: {{ . }}
{{- end }}
{{- if .CommitURL }}
- Commit: {{ .CommitURL }}
{{- if .CommitSHA }} ({{ $t }}{{ .CommitSHA }}{{ $t }}){{ end }}
{{- end }}
{{- with .TarballURL }}
- Tarball: {{ . }}
{{- end }}
{{- with .BuildLogURL }}
- Build Log: {{ . }} (available for 90 days)
{{- end }}`,
))
type bodyData struct {
SourceURL string
CommitSHA string
CommitURL string
BuildLogURL string
TarballURL string
}
func releaseBody(opts *PublishOptions) (string, error) {
src := opts.Source
if src.Repository == nil || src.Commit == nil {
return "", nil
}
data := &bodyData{
SourceURL: src.Repository.TreeURL(src.Ref),
CommitSHA: src.Commit.SHA,
CommitURL: src.Repository.CommitURL(src.Commit.SHA),
TarballURL: src.Repository.TarballURL(src.Commit.SHA),
}
// If available, use the exact value from the build plan.
if src.Tarball != nil {
data.TarballURL = src.Tarball.URL
}
// If running within GitHub Actions, provide link to build log.
if opts.Repository != nil {
if id := os.Getenv("GITHUB_RUN_ID"); id != "" {
data.BuildLogURL = opts.Repository.ActionRunURL(id)
}
}
var buf bytes.Buffer
err := bodyTpl.Execute(&buf, data)
if err != nil {
return "", err
}
return buf.String(), nil
}

View File

@@ -22,8 +22,8 @@ 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"`
Type Type `yaml:"type,omitempty" json:"type,omitempty"`
Source string `yaml:"source,omitempty" json:"source,omitempty"`
}
func NewGitHub(ownerAndName string) (*Repository, error) {
@@ -89,3 +89,42 @@ func (s *Repository) TarballURL(ref string) string {
return ""
}
}
func (s *Repository) CommitURL(ref string) string {
if ref == "" {
return ""
}
switch s.Type {
case GitHub:
return GitHubBaseURL + s.Source + "/commit/" + ref
default:
return ""
}
}
func (s *Repository) TreeURL(ref string) string {
if ref == "" {
return ""
}
switch s.Type {
case GitHub:
return GitHubBaseURL + s.Source + "/tree/" + ref
default:
return ""
}
}
func (s *Repository) ActionRunURL(runID string) string {
if runID == "" {
return ""
}
switch s.Type {
case GitHub:
return GitHubBaseURL + s.Source + "/actions/runs/" + runID
default:
return ""
}
}

17
pkg/source/source.go Normal file
View File

@@ -0,0 +1,17 @@
package source
import (
"github.com/jimeh/build-emacs-for-macos/pkg/commit"
"github.com/jimeh/build-emacs-for-macos/pkg/repository"
)
type Source struct {
Ref string `yaml:"ref,omitempty" json:"ref,omitempty"`
Repository *repository.Repository `yaml:"repository,omitempty" json:"repository,omitempty"`
Commit *commit.Commit `yaml:"commit,omitempty" json:"commit,omitempty"`
Tarball *Tarball `yaml:"tarball,omitempty" json:"tarball,omitempty"`
}
type Tarball struct {
URL string `yaml:"url,omitempty" json:"url,omitempty"`
}