brew-cask: move to using tap cmd directory.

This provides a few benefits:

- faster `brew cask` execution times as another Ruby process is not
  needed. Cask can instead be loaded in-process with Homebrew. This
  will also make it easier to use some of Homebrew's core code and
  ease moving code from Cask into Homebrew core.
- Users do not need to `brew upgrade` Cask any more: it's done
  automatically on any `brew update` or `git pull` of the Cask tap.
This commit is contained in:
Mike McQuaid
2015-12-09 19:32:49 +00:00
parent c8d0a9075d
commit fdb4577be8
16 changed files with 69 additions and 1099 deletions
-170
View File
@@ -1,170 +0,0 @@
#!/bin/bash
#
# brew-cask
#
# bash shim to invoke brew-cask-cmd.rb
#
###
### settings
###
set -e
set -o pipefail
set +o histexpand
set -o nounset
shopt -s nocasematch
shopt -s nullglob
shopt -s dotglob
###
### functions
###
warn () {
local message="$@"
message="${message//\\t/$'\011'}"
message="${message//\\n/$'\012'}"
message="${message%"${message##*[![:space:]]}"}"
printf "%s\n" "$message" 1>&2
}
die () {
warn "$@"
exit 1
}
resolve_dir () {
local resolved="$(for dir; do cd "$dir"; done && /bin/pwd -P)"
if [[ -d "$resolved" ]]; then
printf "%s" "$resolved"
else
die "cannot resolve: '$@'"
fi
}
ensure_dir () {
local dir="$1"
local message
shift
if [ "$#" -gt 0 ]; then
message="$@"
else
message="brew-cask: no such directory: '$dir'"
fi
if ! [[ -d "$dir" ]]; then
die "$message"
fi
}
ensure_file () {
local file="$1"
local message
shift
if [ "$#" -gt 0 ]; then
message="$@"
else
message="brew-cask: no such file: '$file'"
fi
if ! [[ -f "$file" ]]; then
die "$message"
fi
}
ensure_executable () {
local executable="$1"
local message
shift
if [ "$#" -gt 0 ]; then
message="$@"
else
message="brew-cask: no such executable: '$executable'"
fi
if ! [[ -f "$executable" ]] || ! [[ -x "$executable" ]]; then
die "$message"
fi
}
# NOTE: Keep in sync with `Ruby20Requirement` in `/brew-cask.rb`.
find_ruby_2_plus () {
declare -a rubies
local favorite_ruby="/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby"
local version_str
if [[ -x "$favorite_ruby" ]]; then
printf "%s" "$favorite_ruby"
else
IFS=$'\n' rubies=( $(/usr/bin/type -aP ruby) \
"/usr/local/bin/ruby" \
"$(brew --repository 2>/dev/null)/bin/ruby" )
for ruby in "${rubies[@]}"; do
version_str="$("$ruby" --version 2>/dev/null)"
if [[ "$version_str" =~ ^ruby.2 ]]; then
printf "%s" "$ruby"
break
fi
done
fi
}
###
### main
###
_brew_cask () {
local script_dir
local symlink_target
local symlink_target_dir
local brewcask_lib_dir
local brewcask_command
local interpreter
declare -a ruby_opts
ruby_opts=( "-W0" "-EUTF-8:UTF-8" )
script_dir="$(resolve_dir "${0%/*}")"
ensure_dir "$script_dir" \
"brew-cask: could not resolve script directory"
# return "." in case we are not a link
symlink_target="$(/usr/bin/readlink "$0" || echo ".")"
# redefine script_dir because we are likely to be a relative link
symlink_target_dir="$(/usr/bin/dirname "$symlink_target")"
script_dir="$(resolve_dir "$script_dir" "$symlink_target_dir")"
ensure_dir "$script_dir" \
"brew-cask: could not resolve script directory"
# The Homebrew install process replaces the lib element below with rubylib
brewcask_lib_dir="$(resolve_dir "$script_dir"/../lib)"
ensure_dir "$brewcask_lib_dir" \
"brew-cask: could not resolve homebrew-cask library directory"
brewcask_command="$brewcask_lib_dir/brew-cask-cmd.rb"
ensure_file "$brewcask_command" \
"brew-cask: could not find brew-cask-cmd.rb in '$brewcask_lib_dir'"
interpreter="$(find_ruby_2_plus)"
ensure_executable "$interpreter" \
"brew-cask: could not find Ruby 2.0 or greater. Try 'brew install ruby'."
exec "$interpreter" "${ruby_opts[@]}" "$brewcask_command" "${@}"
}
###
### initialization
###
unset GEM_HOME
unset GEM_PATH
###
### dispatch
###
_brew_cask "${@:-}"
#
+9 -62
View File
@@ -1,73 +1,20 @@
begin
require Pathname(__FILE__).realpath.dirname.join("lib", "hbc", "version")
rescue
# todo: transitional, defensive, should not be needed.
# remove the begin/rescue logic after 1 Feb 2015
require Pathname(__FILE__).realpath.dirname.join("lib", "cask", "version")
HBC_VERSION = HOMEBREW_CASK_VERSION
end
# NOTE: Keep in sync with `find_ruby_2_plus` in `/bin/brew-cask`.
class Ruby20Requirement < Requirement
fatal true
default_formula "ruby"
satisfy :build_env => false do
result = false
favorite_ruby =
"/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby"
if File.executable?(favorite_ruby)
result = true
else
rubies = `/usr/bin/type -aP ruby`.split("\n")
rubies += [
"/usr/local/bin/ruby",
"#{`brew --repository 2>/dev/null`.strip}/bin/ruby",
]
rubies.uniq.each do |ruby|
version = /\d\.\d/.match(`#{ruby} --version 2>/dev/null`)
if version && Version.new(version.to_s) >= Version.new("2.0")
result = true
break
end
end
end
result
end
env do
ENV.prepend_path "PATH", which("ruby").dirname
end
def message; <<-EOS.undent
brew-cask needs Ruby >=2.0
EOS
end
end
class BrewCask < Formula
homepage "https://github.com/caskroom/homebrew-cask/"
url "https://github.com/caskroom/homebrew-cask.git", :tag => "v#{HBC_VERSION}"
head "https://github.com/caskroom/homebrew-cask.git", :branch => "master"
url "https://github.com/caskroom/homebrew-cask.git", :tag => "v0.60.0"
skip_clean "bin"
depends_on Ruby20Requirement
depends_on :ruby => "2.0"
def install
man1.install "doc/man/brew-cask.1"
prefix.install "lib" => "rubylib"
inreplace "bin/brew-cask", "/lib", "/rubylib"
end
prefix.install "Casks", "bin"
(bin+"brew-cask").chmod 0755
def caveats
<<-EOS.undent
You can uninstall this formula as `brew tap Caskroom/cask` is now all that's
needed to install Homebrew Cask and keep it up to date.
EOS
end
test do
system "#{bin}/brew-cask", "cask", "info", "google-chrome"
system "brew", "cask", "info", "google-chrome"
end
end
+31
View File
@@ -0,0 +1,31 @@
#!/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby -W0 -EUTF-8:UTF-8
# encoding: UTF-8
# Ruby version check
unless RUBY_VERSION.split(".").first.to_i >= 2
alt_ruby = which "ruby"
alt_ruby_version = `#{alt_ruby} --version`.chomp[/\d\.\d/, 0] if alt_ruby
unless alt_ruby && alt_ruby_version.split(".").first.to_i >= 2
abort "Ruby 2.0 or above is required. You can install it with `brew install ruby`."
end
exec alt_ruby, "-W0", "-I#{HOMEBREW_LIBRARY_PATH}", "-rglobal", __FILE__, *ARGV
end
require 'pathname'
$LOAD_PATH.unshift(File.expand_path('../../lib', Pathname.new(__FILE__).realpath))
# todo remove internal Homebrew dependencies and remove this line
require 'vendor/homebrew-fork/global'
require 'hbc'
begin
Hbc::CLI.process(ARGV)
rescue Interrupt => e
puts
exit 130
end
exit 0
-118
View File
@@ -1,118 +0,0 @@
#!/usr/bin/env ruby
#
# bump_version
#
###
### dependencies
###
require 'open3'
require 'rubygems'
###
### configurable constants
###
VERSION_FILE = 'lib/hbc/version.rb'
VERSION_PAT = %r[\d+\.\d+\.\d+]i
VERSION_CONSTANT_NAME = 'HBC_VERSION'
###
### methods
###
def cd_to_project_root
Dir.chdir File.dirname(File.expand_path(__FILE__))
@git_root ||= Open3.popen3(*%w[
git rev-parse --show-toplevel
]) do |stdin, stdout, stderr|
begin
stdout.gets.chomp
rescue
end
end
Dir.chdir @git_root
@git_root
end
def git_diff
Open3.popen3(*%w[
git diff --no-color --
],
VERSION_FILE) do |stdin, stdout, stderr|
stdout.each_line.map(&:chomp)
end
end
def file_contents_pat
%r{\A(#{VERSION_CONSTANT_NAME}\s+=\s+)'(#{VERSION_PAT})'\s*\Z}s
end
def current_file_contents
@current_file_contents ||= File.read(VERSION_FILE)
end
def current_file_version
if file_contents_pat.match(current_file_contents)
$2
else
raise "Could not parse file '#{VERSION_FILE}'"
end
end
def sanity_check
unless %r{\A#{VERSION_PAT}\Z}.match(proposed_version)
raise "Proposed version '#{proposed_version}' does not look like a semantic version string"
end
unless %r{\A#{VERSION_PAT}\Z}.match(current_file_version)
raise "Current version '#{current_file_version}' does not look like a semantic version string"
end
unless Gem::Version.new(proposed_version) > Gem::Version.new(current_file_version)
raise "Proposed version '#{proposed_version}' is not greater than current version #{current_file_version}"
end
end
def usage
<<EOT
bump_version <new-version>
Bump the version number in #{VERSION_FILE} to match the
number given on the command line.
EOT
end
def proposed_version
@proposed_version ||= ARGV.first.sub(/^v/i, '')
end
def rewrite_version
new_file_contents = current_file_contents
if new_file_contents.sub!(file_contents_pat, "\\1'#{proposed_version}'\n")
File.open(VERSION_FILE, 'w') {|f| f.write(new_file_contents) }
else
raise "Could not parse file '#{VERSION_FILE}'"
end
end
###
### main
###
# process args
if %r{\A-+h(?:elp)?}i.match(ARGV.first)
puts usage
exit
elsif ARGV.length != 1 or ! %r{\Av?#{VERSION_PAT}\Z}.match(ARGV.first)
puts usage
exit 1
end
# initialize
cd_to_project_root
# dispatch
sanity_check
rewrite_version
puts git_diff
-364
View File
@@ -1,364 +0,0 @@
#!/usr/bin/env ruby
#
# generate_changelog
#
###
### dependencies
###
require 'open3'
require 'set'
###
### configurable constants
###
PROJECT_URL = 'https://github.com/caskroom/homebrew-cask'
MAINTAINERS = %w[
phinze
fanquake
vitorgalvao
alebcay
ndr-qef
jawshooah
sebroeder
adityadalal924
caskroom
]
CODE_PATHS = %w[
bin
developer
lib
spec
test
brew-cask.rb
Rakefile
Gemfile
Gemfile.lock
.travis.yml
.gitignore
]
SHA_PAT = '[\da-f]{40}'
###
### monkeypatching
###
class Array
def to_h
Hash[*self.flatten]
end
end
###
### git methods
###
def end_object
'HEAD'
end
def matches_sha(sha)
%r{\A#{SHA_PAT}\Z}.match(sha)
end
def cd_to_project_root
Dir.chdir File.dirname(File.expand_path(__FILE__))
@git_root ||= Open3.popen3(*%w[
git rev-parse --show-toplevel
]) do |stdin, stdout, stderr|
begin
stdout.gets.chomp
rescue
end
end
Dir.chdir @git_root
@git_root
end
def warn_if_off_branch(wanted_branch='master')
current_branch = Open3.popen3(*%w[
git rev-parse --abbrev-ref HEAD
]) do |stdin, stdout, stderr|
begin
stdout.gets.chomp
rescue
end
end
unless current_branch == wanted_branch
$stderr.puts "\nWARNING: you are running from branch '#{current_branch}', not '#{wanted_branch}'\n\n"
end
end
def last_release
@last_release ||= Open3.popen3(
'./developer/bin/get_release_tag'
) do |stdin, stdout, stderr|
begin
stdout.gets.chomp
rescue
end
end
end
def next_release
if @next_release.nil?
if ENV.key?('NEW_RELEASE_TAG')
@next_release = ENV['NEW_RELEASE_TAG']
else
@next_release = Open3.popen3(
'./developer/bin/get_release_tag', '-next'
) do |stdin, stdout, stderr|
begin
stdout.gets.chomp
rescue
end
end
end
else
@next_release
end
end
def verify_git_object(object)
sha = Open3.popen3(*%w[
git rev-parse -q --verify
],
object, '--'
) do |stdin, stdout, stderr|
begin
stdout.gets.chomp
rescue
end
end
raise "'#{object}' is not a git object" unless matches_sha sha
sha
end
# constrained to last_release..HEAD
def all_shas
@all_shas ||= Open3.popen3(*%w[
git rev-list --topo-order
],
"#{last_release}..#{end_object}"
) do |stdin, stdout, stderr|
stdout.each_line.map(&:chomp)
end
end
# not constrained
def tag_commits
@tag_commits ||= Open3.popen3(*%w[
git show-ref -s --tags --dereference
]) do |stdin, stdout, stderr|
stdout.each_line.collect do |line|
line.chomp!
if ! %r{\^\{\}\Z}.match(line)
nil
elsif %r{\A(#{SHA_PAT}) }.match(line)
[$1, true]
else
raise "'#{line}' does not contain an SHA"
end
end.compact.to_h
end
end
# Collect merge commits separately because "git log" does not always
# return related merge commits when using a path constraint. There
# might be a clever way to do this in a single step already built into
# git. In any case (in the opinion of the author) git's default
# behavior is a bug.
#
# constrained to last_release..HEAD
def merge_commits
@merge_commits ||= Open3.popen3(*%w[
git rev-list --pretty=oneline --topo-order --min-parents=2 --max-parents=2 --parents
],
"#{last_release}..#{end_object}"
) do |stdin, stdout, stderr|
stdout.each_line.collect do |line|
line.chomp!
# intentionally limited to the simple case of two parents
if %r{\A(#{SHA_PAT}) (#{SHA_PAT}) (#{SHA_PAT}) (.*)}.match(line)
[$1, {
:trunk_parent => $2,
:branch_parent => $3,
:log => $4,
}]
else
raise "could not parse '#{line}'"
end
end.compact.to_h
end
end
# constrained to last_release..HEAD
# also constrained to CODE_PATHS
def ordinary_code_commits
@ordinary_code_commits ||= Open3.popen3(*%w[
git rev-list --pretty=oneline --topo-order --max-parents=1 --parents
],
"#{last_release}..#{end_object}",
'--', *CODE_PATHS
) do |stdin, stdout, stderr|
stdout.each_line.collect do |line|
line.chomp!
if %r{\A(#{SHA_PAT}) (#{SHA_PAT}) (.*)}.match(line)
[$1, {
:trunk_parent => $2,
:log => $3,
}]
else
raise "could not parse '#{line}'"
end
end.compact.to_h
end
end
###
### report/analysis methods
###
# todo: read the release date from the tag
def header
<<EOT
## #{next_release.sub(/^v/,'')}
* __Casks__
- N Casks added ...
- N total Casks
* __Features__
- none
* __Breaking Changes__
- none
* __Fixes__
- none
* __Internal Changes__
- none
* __Documentation__
- N doc commits since ...
* __Contributors__
- N new contributors since ...
- N total contributors
* __Release Date__
- YYYY-MM-DD HH:MM:SS UTC
EOT
end
def footer
@footer ||= Set.new
@footer.to_a.sort
end
def add_to_footer(line)
@footer ||= Set.new
@footer.add line
end
def seen(sha)
@seen ||= {}
if @seen[sha]
return true
else
@seen[sha] = true
return nil
end
end
def log_ordinary_commit(sha)
# indent ordinary commits
" - #{ordinary_code_commits[sha][:log]}"
end
def read_pull_request(sha)
branch_parent = merge_commits[sha][:branch_parent]
if ordinary_code_commits[branch_parent] and
%r{\AMerge pull request \#(\d+) from ([^\s/]+)}.match(merge_commits[sha][:log]) then
{
:num => $1,
:gh_user => MAINTAINERS.include?($2) ? '' : $2
}
end
end
def log_merge_commit(sha)
branch_parent = merge_commits[sha][:branch_parent]
pr = read_pull_request sha
if pr then
# munge a GitHub PR commit log entry into Markdown links
# plus log content from the first parent commit
log = "[##{pr[:num]}][]"
log.concat " #{ordinary_code_commits[branch_parent][:log]}"
add_to_footer "[##{pr[:num]}]: #{PROJECT_URL}/issues/#{pr[:num]}"
seen branch_parent
if pr[:gh_user].length > 0
log.concat " <3 [@#{pr[:gh_user]}][]"
add_to_footer "[@#{pr[:gh_user]}]: https://github.com/#{pr[:gh_user]}"
end
" - #{log}"
elsif ordinary_code_commits[branch_parent]
# non-PR merge, just pass the log msg unmodified
" - #{merge_commits[sha][:log]}"
else
# drop this merge, it does not relate to CODE_PATHS
end
end
def changelog
# follows topological order
all_shas.collect do |sha|
if tag_commits[sha]
nil
elsif seen sha
nil
elsif ordinary_code_commits[sha]
log_ordinary_commit sha
elsif merge_commits[sha]
log_merge_commit sha
end
end.compact
end
###
### main
###
# process args
if %r{\A-+h(?:elp)?}i.match(ARGV.first)
puts <<EOT
generate_changelog [ <release-tag> ]
Generate a rough-draft changelog in Markdown format for changes since
<release-tag>, which defaults to the most recent release.
The output is only a draft. Changelog items still need to be edited,
removed, and/or added.
All changelog items must also be moved to within one of the given
category sections.
EOT
exit
end
if ARGV.length
@last_release = ARGV.shift
end
# initialize
cd_to_project_root
verify_git_object last_release
warn_if_off_branch 'master'
# report
puts header
puts "\n"
puts changelog
puts "\n"
puts footer
puts "\n"
+1 -1
View File
@@ -50,6 +50,6 @@ if ! /usr/bin/which ronn >/dev/null 2>&1; then
die "ERROR: The 'ronn' gem must be installed"
fi
ronn --roff --pipe --organization='Homebrew-cask' --manual='brew-cask' doc/src/brew-cask.1.md > doc/man/brew-cask.1
ronn --roff --pipe --organization='Homebrew-cask' --manual='brew-cask' doc/src/brew-cask.1.md > man/man1/brew-cask.1
#
-191
View File
@@ -1,191 +0,0 @@
#!/bin/bash
#
# get_release_tag
#
###
### settings
###
set -e # exit on any uncaught error
set +o histexpand # don't expand history expressions
shopt -s nocasematch # case-insensitive regular expressions
###
### global variables
###
opt_next=''
opt_latest=''
opt_verbose=''
###
### functions
###
warn () {
local message="$@"
message="${message//\\t/$'\011'}"
message="${message//\\n/$'\012'}"
message="${message%"${message##*[![:space:]]}"}"
printf "%s\n" "$message" 1>&2
}
die () {
warn "$@"
exit 1
}
cd_to_project_root () {
local script_dir="$(/usr/bin/dirname "$0")"
cd "$script_dir"
local git_root="$(git rev-parse --show-toplevel)"
if [[ -z "$git_root" ]]; then
die "ERROR: Could not find git project root"
fi
cd "$git_root"
}
verify_git_object_is_new () {
if git rev-parse --verify "$1" >/dev/null 2>&1; then
die "\nERROR: Proposed new tag: '$1' already exists as a commit object\n\n"
fi
}
sanity_check_parsed_version () {
if [[ $# -ne 3 ]]; then
die "ERROR: Could not parse version tag: wrong number of elements"
fi
if ! [[ $1 =~ ^v[0-9]+$ ]]; then
die "ERROR: Could not parse version tag: does not start with v[0-9]"
fi
}
output_proposed_tag () {
local new_tag="$1.$2.$3"
sanity_check_parsed_version "$@"
verify_git_object_is_new "$new_tag"
if [[ -n "$opt_verbose" ]]; then
printf "Latest tag\t%s\n" "$latest_tag"
printf "Proposed new tag\t%s\n" "$new_tag"
else
printf "%s\n" "$new_tag"
fi
}
generate_next_major_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1"
sanity_check_parsed_version "${version_elts[@]}"
version_elts[0]="${version_elts[0]#v}" # mangle v<digit> into number
(( version_elts[0] += 1 )) # increment version field
version_elts[0]="v${version_elts[0]}" # restore text v<digit>
version_elts[1]='0' # reset minor field
version_elts[2]='0' # reset patch field
output_proposed_tag "${version_elts[@]}"
}
generate_next_minor_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1"
sanity_check_parsed_version "${version_elts[@]}"
(( version_elts[1] += 1 )) # increment minor field
version_elts[2]='0' # reset patch field
output_proposed_tag "${version_elts[@]}"
}
generate_next_patch_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1"
sanity_check_parsed_version "${version_elts[@]}"
(( version_elts[2] += 1 )) # increment patch field
output_proposed_tag "${version_elts[@]}"
}
process_args () {
local arg
for arg in "$@"; do
if [[ $arg =~ ^-+h(elp)?$ ]]; then
printf "get_release_tag [ -latest | -next | -patch | -major | -verbose | -help ]
Retrieve or calculate a release tag.
Arguments:
-latest Show the most recent tag in the repository, which is typically
the designation of the latest release. This is the default
when invoked with no arguments.
-next Calculate the next minor-release tag bump and return it.
-patch Calculate the next patch-release tag bump and return it.
Overrides -next if both are given.
-major Calculate the next major-release tag bump and return it.
Overrides -next if both are given.
-verbose Output a table, possibly including both latest existing and
proposed new tags.
See doc/releasing.md for more information.
"
exit
elif [[ $arg =~ ^-+v(erbose)?$ ]]; then
opt_verbose='true'
elif [[ $arg =~ ^-+next$ ]]; then
if [[ -z "$opt_next" ]]; then
opt_next='minor'
fi
elif [[ $arg =~ ^-+patch$ ]]; then
if [[ "$opt_next" == 'major' ]]; then
die "ERROR: -patch is incompatible with -major"
fi
opt_next='patch'
elif [[ $arg =~ ^-+major$ ]]; then
if [[ "$opt_next" == 'patch' ]]; then
die "ERROR: -patch is incompatible with -major"
fi
opt_next='major'
elif [[ $arg =~ ^-+latest$ ]]; then
opt_latest='true'
else
die "ERROR: Unknown argument '$arg'"
fi
if [[ -n "$opt_latest" && -n "$opt_next" ]]; then
die "ERROR: -latest is incompatible with -next/-patch/-major"
fi
done
}
###
### main
###
_get_release_tag () {
cd_to_project_root
local latest_tag="$(git describe --tags --abbrev=0 2>/dev/null)"
if [[ -z "$latest_tag" ]]; then
die "ERROR: No recent tag found"
elif [[ -z "$opt_next" ]]; then
if [[ -n "$opt_verbose" ]]; then
printf "Latest tag\t"
fi
printf "%s\n" "$latest_tag"
elif [[ "$opt_next" == 'major' ]]; then
generate_next_major_tag "$latest_tag"
elif [[ "$opt_next" == 'minor' ]]; then
generate_next_minor_tag "$latest_tag"
elif [[ "$opt_next" == 'patch' ]]; then
generate_next_patch_tag "$latest_tag"
else
die "ERROR: Should not happen. Unknown argument?"
fi
}
process_args "${@}"
# dispatch main
_get_release_tag
#
-154
View File
@@ -1,154 +0,0 @@
# Release Standards
Heres where we document how homebrew-cask is released.
## Versioning
We attempt to follow [Semantic Versioning](http://semver.org/) as much as possible.
Since we are still pre-1.0, this essentially means that we bump the PATCH number when we fix bugs, and we bump the MINOR number when we add features. Pretty simple.
The script `./developer/bin/get_release_tag` can tell you the latest release tag that exists and/or calculate the proposed next release tag. Docs are at `get_release_tag -help`.
## Release Process
This is partially scripted now. The most time-consuming step is editing the changelog.
1. Be running on a checkout of `master` which is up to date and `git status`
clean:
```bash
$ git checkout master && git status
```
2. `cd` to the project root:
```bash
$ cd "$(git rev-parse --show-toplevel)"
```
3. Pull in the latest `master`:
```bash
$ git pull https://github.com/caskroom/homebrew-cask master
```
4. Compile the man page and check the result by running:
```bash
$ ./developer/bin/generate_man_pages; git --no-pager diff ./doc/man/brew-cask.1
```
If the newly-compiled man page has no changes other than the datestamp, you may wish to discard the changes as follows:
```bash
$ git checkout -- ./doc/man/brew-cask.1 # discard changes
```
5. Do a `git log` to see what changed since the last release. You can scope it to only code changes:
```bash
$ git log "$(./developer/bin/get_release_tag)"..HEAD -- lib spec test developer bin Gemfile Gemfile.lock Rakefile brew-cask.rb
```
6. Decide whether to bump the minor or patch field in the next release tag, based on whether or not features were added. For a feature release, run the shell command:
```bash
$ export NEW_RELEASE_TAG="$(./developer/bin/get_release_tag -next)"; echo "$NEW_RELEASE_TAG"
```
or for a patch release, add `-patch` to the command:
```bash
$ export NEW_RELEASE_TAG="$(./developer/bin/get_release_tag -next -patch)"; echo "$NEW_RELEASE_TAG"
```
7. Make sure the value in `$NEW_RELEASE_TAG` is what you want.
8. Bump the `HBC_VERSION` string which is stored in the file `lib/hbc/version.rb`:
```bash
$ ./developer/bin/bump_version "$NEW_RELEASE_TAG"
```
The version string in the Ruby code should match `$NEW_RELEASE_TAG`, except that the Ruby version should lack the leading `v` character.
9. Generate a draft changelog for the new release by running:
```bash
$ ./developer/bin/project_stats release >| /var/tmp/draft_release_changelog.md
$ ./developer/bin/generate_changelog >> /var/tmp/draft_release_changelog.md
```
10. Edit the draft changelog, following the patterns used in `doc/CHANGELOG.md`. Some of the items for the changelog should be extracted from the statistics section at the start of the file, after which the statistics section can be deleted.
11. When complete, insert the new release changelog near the beginning of `doc/CHANGELOG.md`, just after the first line.
12. Make a commit on `master` with the modifications to `doc/CHANGELOG.md`, `lib/hbc/version.rb`, and/or `doc/man/brew-cask.1`:
```bash
$ git add doc/CHANGELOG.md lib/hbc/version.rb doc/man/brew-cask.1
$ git commit -m "cut $NEW_RELEASE_TAG"
```
13. Pull to get changes since you started working on the changelog:
```bash
$ git pull https://github.com/caskroom/homebrew-cask master
```
14. Tag the tip commit. Make certain to provide a `-m` message so that we get an annotated tag in the git history:
```bash
$ git tag -m "$NEW_RELEASE_TAG" "$NEW_RELEASE_TAG"
```
15. Push that commit and the tag:
```bash
$ git push https://github.com/caskroom/homebrew-cask master && git push https://github.com/caskroom/homebrew-cask tag "$NEW_RELEASE_TAG" && echo "new release $NEW_RELEASE_TAG was successfully pushed"
```
If you dont see a success message, that probably means someone updated master while you were working on the changelog. You must pull and resolve.
16. Open your browser to the relevant release page on GitHub:
```bash
$ open "https://github.com/caskroom/homebrew-cask/releases/new?tag=$NEW_RELEASE_TAG"
```
17. On the release page:
* If the `Tag version` field does not auto-fill, manually select the tag
you just created (shell variable `$NEW_RELEASE_TAG`).
* Paste the Markdown summary for the new release from `doc/CHANGELOG.md`
into the main textarea.
* Do not include the `## <version number>` heading line from the changelog
in the pasted text.
* The `Release title` field may be left blank.
18. Click `Publish Release`.
19. Unset the shell variable `$NEW_RELEASE_TAG`; you dont need it anymore:
```bash
$ unset NEW_RELEASE_TAG
```
20. Announce the release on IRC.
21. Respond to any pending GitHub issues which may be resolved after users upgrade.
22. Rejoice! Have a :cookie:.
## Things to Consider
The way `brew update` works, users will always be tracking `HEAD` in their Tap. This means that the latest updates to Casks are always propagated ahead of code releases. We need to be thoughtful about how we push out new or breaking functionality. As a pre-1.0 project we can still break backwards compatibility, but sometimes there might be decisions we can make about releasing to make things easier on our users.
In general: go easy on the users!
## Notes
* In steps 3 and 14:
- The full URL is given for the repo because that does not change depending on your local `.git/config`. Equivalent commands may be `git push`, `git push origin master`, or `git push upstream master`.
- We push the commits *before* pushing the tag to ensure that there are no conflicts. The default behavior of `git push --follow-tags` is to push tags to the public repo before commits, which caused the “lost” tag v0.39.0.
-24
View File
@@ -1,24 +0,0 @@
#!/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby -W0 -EUTF-8:UTF-8
# encoding: UTF-8
# just in case
if RUBY_VERSION.to_i < 2
raise 'brew-cask: Ruby 2.0 or greater is required.'
end
require 'pathname'
$LOAD_PATH.unshift(File.expand_path('..', Pathname.new(__FILE__).realpath))
# todo remove internal Homebrew dependencies and remove this line
require 'vendor/homebrew-fork/global'
require 'hbc'
begin
Hbc::CLI.process(ARGV)
rescue Interrupt => e
puts
exit 130
end
exit 0
+1 -1
View File
@@ -229,7 +229,7 @@ class Hbc::CLI
def run(*args)
if args.include?('--version') or @attempted_verb == '--version'
puts HBC_VERSION
puts Hbc.full_version
else
purpose
usage
+7 -11
View File
@@ -11,7 +11,7 @@ class Hbc::CLI::Doctor < Hbc::CLI::Base
ohai 'Homebrew Cellar Path:', render_with_none_as_error( homebrew_cellar )
ohai 'Homebrew Repository Path:', render_with_none_as_error( homebrew_repository )
ohai 'Homebrew Origin:', render_with_none_as_error( homebrew_origin )
ohai 'Homebrew-cask Version:', render_with_none_as_error( HBC_VERSION )
ohai 'Homebrew-cask Version:', render_with_none_as_error( Hbc.full_version )
ohai 'Homebrew-cask Install Location:', render_install_location( HBC_VERSION )
ohai 'Homebrew-cask Staging Location:', render_staging_location( Hbc.caskroom )
ohai 'Homebrew-cask Cached Downloads:', render_cached_downloads
@@ -93,9 +93,9 @@ class Hbc::CLI::Doctor < Hbc::CLI::Base
homebrew_constants('version')
end
def self.homebrew_libdir
@homebrew_libdir ||= if homebrew_repository.respond_to?(:join)
homebrew_repository.join('Library', 'Homebrew')
def self.homebrew_taps
@homebrew_taps ||= if homebrew_repository.respond_to?(:join)
homebrew_repository.join('Library', 'Taps')
end
end
@@ -206,14 +206,10 @@ class Hbc::CLI::Doctor < Hbc::CLI::Base
return "#{none_string} #{error_string}"
end
copy = Array.new(paths)
unless Hbc::Utils.file_is_descendant(copy[0], homebrew_cellar)
copy[0] = "#{copy[0]} #{error_string %Q{error: should be descendant of Homebrew Cellar}}"
end
copy.map! do |elt|
elt = (homebrew_libdir and Hbc::Utils.file_is_descendant(elt, homebrew_libdir)) ?
"#{elt} #{error_string %Q{error: should not be descendant of Homebrew Library dir}}" :
elt
unless Hbc::Utils.file_is_descendant(copy[0], homebrew_taps)
copy[0] = "#{copy[0]} #{error_string %Q{error: should be descendant of Homebrew taps directory}}"
end
copy
end
def self.render_cached_downloads
+4
View File
@@ -100,6 +100,10 @@ module Hbc::Locations
@default_tap = _tap
end
def default_tappath
@default_tappath ||= homebrew_tapspath.join(default_tap)
end
def path(query)
if query.include?('/')
token_with_tap = query
+13 -1
View File
@@ -1 +1,13 @@
HBC_VERSION = '0.59.0'
HBC_VERSION = '0.60.0'
module Hbc
def self.full_version
@full_version ||= begin
revision, commit = Dir.chdir(Hbc.default_tappath) do
[`git rev-parse --short=4 --verify -q HEAD 2>/dev/null`.chomp,
`git show -s --format="%cr" HEAD 2>/dev/null`.chomp]
end
"#{HBC_VERSION} (git revision #{revision}; last commit #{commit})"
end
end
end
+1 -1
View File
@@ -4,6 +4,6 @@ describe 'brew cask --version' do
it 'respects the --version argument' do
lambda {
Hbc::CLI::NullCommand.new('--version').run
}.must_output "#{HBC_VERSION}\n"
}.must_output "#{Hbc.full_version}\n"
end
end
+2 -1
View File
@@ -26,10 +26,11 @@ describe "Repo layout" do
TOPLEVEL_DIRS = %w{
.git
Casks
bin
cmd
developer
doc
lib
man
spec
test
}