Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
一个人扛起一支队伍
brew
提交
fb5aefd4
B
brew
项目概览
一个人扛起一支队伍
/
brew
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
B
brew
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
fb5aefd4
编写于
7月 24, 2009
作者:
M
Max Howell
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor--object orientate where sensible
上级
5eb9d651
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
682 addition
and
613 deletion
+682
-613
Library/Homebrew/brewkit.rb
Library/Homebrew/brewkit.rb
+3
-368
Library/Homebrew/env.rb
Library/Homebrew/env.rb
+94
-1
Library/Homebrew/formula.rb
Library/Homebrew/formula.rb
+263
-0
Library/Homebrew/keg.rb
Library/Homebrew/keg.rb
+153
-0
Library/Homebrew/unittest.rb
Library/Homebrew/unittest.rb
+1
-1
README
README
+23
-10
bin/brew
bin/brew
+145
-233
未找到文件。
Library/Homebrew/brewkit.rb
浏览文件 @
fb5aefd4
...
...
@@ -15,9 +15,8 @@
# You should have received a copy of the GNU General Public License
# along with Homebrew. If not, see <http://www.gnu.org/licenses/>.
require
'pathname'
require
'osx/cocoa'
# to get number of cores
require
'
env
'
require
'
formula
'
# optimise all the way to eleven, references:
# http://en.gentoo-wiki.com/wiki/Safe_Cflags/Intel
...
...
@@ -38,343 +37,7 @@ unless $root.to_s == '/usr/local'
end
def
ohai
title
n
=
`tput cols`
.
strip
.
to_i
-
4
puts
"
\033
[0;34m==>
\033
[0;0;1m
#{
title
[
0
,
n
]
}
\033
[0;0m"
end
def
cache
cache
=
File
.
expand_path
"~/Library/Caches/Homebrew"
FileUtils
.
mkpath
cache
return
cache
end
class
BuildError
<
RuntimeError
def
initialize
cmd
super
"Build failed during:
#{
cmd
}
"
end
end
# pass in the basename of the filename _without_ any file extension
def
extract_version
basename
# eg. boost_1_39_0
/((\d+_)+\d+)$/
.
match
basename
return
$1
.
gsub
(
'_'
,
'.'
)
if
$1
# eg. foobar-4.5.1-1
/-((\d+\.)*\d+-\d+)$/
.
match
basename
return
$1
if
$1
# eg. foobar-4.5.1
/-((\d+\.)*\d+)$/
.
match
basename
return
$1
if
$1
# eg. foobar-4.5.1b
/-((\d+\.)*\d+([abc]|rc\d))$/
.
match
basename
return
$1
if
$1
# eg foobar-4.5.0-beta1
/-((\d+\.)*\d+-beta\d+)$/
.
match
basename
return
$1
if
$1
# eg. foobar4.5.1
/((\d+\.)*\d+)$/
.
match
basename
return
$1
if
$1
# eg. otp_src_R13B (this is erlang's style)
# eg. astyle_1.23_macosx.tar.gz
basename
.
scan
/_([^_]+)/
do
|
match
|
return
match
.
first
if
/\d/
.
match
$1
end
end
# make our code neater
class
Pathname
def
mv
dst
FileUtils
.
mv
to_s
,
dst
end
def
rename
dst
dst
=
Pathname
.
new
dst
dst
.
unlink
if
dst
.
exist?
mv
dst
end
def
install
src
if
src
.
is_a?
Array
src
.
each
{
|
src
|
install
src
}
elsif
File
.
exist?
src
mkpath
if
File
.
symlink?
src
# we cp symlinks because FileUtils.mv is shit and won't mv a symlink
# if its final destination has an invalid target! FFS. Ruby is shit.
FileUtils
.
cp
src
,
to_s
else
# we mv when possible as it is faster and you should only be using
# this function when installing from the temporary build directory
FileUtils
.
mv
src
,
to_s
end
end
end
def
cp
dst
if
file?
FileUtils
.
cp
to_s
,
dst
else
FileUtils
.
cp_r
to_s
,
dst
end
end
# for filetypes we support
def
extname
/\.(zip|tar\.(gz|bz2)|tgz)$/
.
match
to_s
return
".
#{
$1
}
"
if
$1
return
File
.
extname
(
to_s
)
end
# for filetypes we support, basename without extension
def
stem
return
File
.
basename
(
to_s
,
extname
)
end
end
# the base class variety of formula, you don't get a prefix, so it's not really
# useful. See the derived classes for fun and games.
class
AbstractFormula
require
'find'
require
'fileutils'
# fuck knows, ruby is weird
# TODO please fix!
def
self
.
url
@url
end
def
url
self
.
class
.
url
end
def
self
.
md5
@md5
end
def
md5
self
.
class
.
md5
end
def
self
.
homepage
@homepage
end
def
homepage
self
.
class
.
homepage
end
# end ruby is weird section
def
version
@version
end
def
name
@name
end
def
initialize
name
=
nil
@name
=
name
# fuck knows, ruby is weird
@url
=
url
if
@url
.
nil?
raise
"@url.nil?"
if
@url
.
nil?
@md5
=
md5
if
@md5
.
nil?
# end ruby is weird section
end
public
def
prefix
raise
"@name.nil!"
if
@name
.
nil?
raise
"@version.nil?"
if
@version
.
nil?
$cellar
+
@name
+
@version
end
def
bin
prefix
+
'bin'
end
def
doc
prefix
+
'share'
+
'doc'
+
name
end
def
man
prefix
+
'share'
+
'man'
end
def
man1
prefix
+
'share'
+
'man'
+
'man1'
end
def
lib
prefix
+
'lib'
end
def
include
prefix
+
'include'
end
def
caveats
nil
end
# yields self with current working directory set to the uncompressed tarball
def
brew
ohai
"Downloading
#{
@url
}
"
Dir
.
chdir
cache
do
tmp
=
tgz
=
nil
begin
tgz
=
Pathname
.
new
(
fetch
()).
realpath
md5
=
`md5 -q "
#{
tgz
}
"`
.
strip
raise
"MD5 mismatch:
#{
md5
}
"
unless
@md5
and
md5
==
@md5
.
downcase
# we make an additional subdirectory so know exactly what we are
# recursively deleting later
# we use mktemp rather than appsupport/blah because some build scripts
# can't handle being built in a directory with spaces in it :P
tmp
=
`mktemp -dt
#{
File
.
basename
@url
}
`
.
strip
Dir
.
chdir
tmp
do
Dir
.
chdir
uncompress
(
tgz
)
do
yield
self
end
end
rescue
Interrupt
,
RuntimeError
if
ARGV
.
include?
'--debug'
# debug mode allows the packager to intercept a failed build and
# investigate the problems
puts
"Rescued build at:
#{
tmp
}
"
exit!
1
else
raise
end
ensure
FileUtils
.
rm_rf
tmp
if
tmp
end
end
end
def
clean
#TODO strip libexec too
[
bin
,
lib
].
each
{
|
path
|
path
.
find
do
|
path
|
if
not
path
.
file?
next
elsif
path
.
extname
==
'.la'
# .la files are stupid
path
.
unlink
else
fo
=
`file -h
#{
path
}
`
args
=
nil
perms
=
0444
if
fo
=~
/Mach-O dynamically linked shared library/
args
=
'-SxX'
elsif
fo
=~
/Mach-O executable/
# defaults strip everything
args
=
''
# still do the strip
perms
=
0544
elsif
fo
=~
/script text executable/
perms
=
0544
end
if
args
puts
"Stripping:
#{
path
}
"
if
ARGV
.
include?
'--verbose'
path
.
chmod
0644
# so we can strip
unless
path
.
stat
.
nlink
>
1
`strip
#{
args
}
#{
path
}
`
else
# strip unlinks the file and recreates it, thus breaking hard links!
# is this expected behaviour? patch does it too… still,mktm this fixes it
tmp
=
`mktemp -t
#{
path
.
basename
}
`
.
strip
`strip -o
#{
tmp
}
#{
path
}
`
`cat
#{
tmp
}
>
#{
path
}
`
File
.
unlink
tmp
end
end
path
.
chmod
perms
end
end
}
# remove empty directories
`perl -MFile::Find -e"finddepth(sub{rmdir},'
#{
prefix
}
')"`
end
protected
def
uncompress
path
path
.
dirname
end
private
def
fetch
%r[http://(www.)?github.com/.*/(zip|tar)ball/]
.
match
@url
if
$2
# curl doesn't do the redirect magic that we would like, so we get a
# stupidly named file, this is why wget would be beter, but oh well
tgz
=
"
#{
@name
}
-
#{
@version
}
.
#{
$2
==
'tar'
?
'tgz'
:
$2
}
"
oarg
=
"-o
#{
tgz
}
"
else
oarg
=
'-O'
#use the filename that curl gets
tgz
=
File
.
expand_path
File
.
basename
(
@url
)
end
agent
=
"Homebrew
#{
HOMEBREW_VERSION
}
(Ruby
#{
VERSION
}
; Mac OS X 10.5 Leopard)"
unless
File
.
exists?
tgz
`curl -#LA "
#{
agent
}
"
#{
oarg
}
"
#{
@url
}
"`
raise
"Download failed"
unless
$?
==
0
else
puts
"File already downloaded and cached"
end
return
tgz
end
def
method_added
method
raise
'You cannot override Formula.brew'
if
method
==
'brew'
end
end
# somewhat useful, it'll raise if you call prefix, but it'll unpack a tar/zip
# for you, check the md5, and allow you to yield from brew
class
UnidentifiedFormula
<
AbstractFormula
def
initialize
name
=
nil
super
name
end
private
def
uncompress
(
path
)
if
path
.
extname
==
'.zip'
`unzip -qq "
#{
path
}
"`
else
`tar xf "
#{
path
}
"`
end
raise
"Compression tool failed"
if
$?
!=
0
entries
=
Dir
[
'*'
]
if
entries
.
nil?
or
entries
.
length
==
0
raise
"Empty tarball!"
elsif
entries
.
length
==
1
# if one dir enter it as that will be where the build is
entries
.
first
else
# if there's more than one dir, then this is the build directory already
Dir
.
pwd
end
end
end
# this is what you will mostly use, reimplement install, prefix won't raise
class
Formula
<
UnidentifiedFormula
def
initialize
name
super
name
@version
=
extract_version
Pathname
.
new
(
File
.
basename
(
@url
)).
stem
unless
@version
end
end
# see ack.rb for an example usage
class
ScriptFileFormula
<
AbstractFormula
def
install
bin
.
install
name
end
end
class
GithubGistFormula
<
ScriptFileFormula
def
initialize
super
File
.
basename
(
url
)
@version
=
File
.
basename
(
File
.
dirname
(
url
))[
0
,
6
]
end
end
######################################################################## utils
def
inreplace
(
path
,
before
,
after
)
before
=
before
.
to_s
.
gsub
(
'"'
,
'\"'
).
gsub
(
'/'
,
'\/'
)
...
...
@@ -385,34 +48,6 @@ def inreplace(path, before, after)
#TODO optimise it by taking before and after as arrays
#Bah, just make the script writers do it themselves with a standard collect block
#TODO use ed -- less to escape
#TODO the above doesn't escape all regexp symbols!
`perl -pi -e "s/
#{
before
}
/
#{
after
}
/g" "
#{
path
}
"`
end
def
system
cmd
ohai
cmd
out
=
''
IO
.
popen
(
"
#{
cmd
}
2>&1"
)
do
|
f
|
until
f
.
eof?
s
=
f
.
gets
if
ARGV
.
include?
'--verbose'
puts
s
else
out
+=
s
end
end
end
unless
$?
==
0
puts
out
unless
ARGV
.
include?
'--verbose'
#already did that above
raise
BuildError
.
new
(
cmd
)
end
end
####################################################################### script
if
$0
==
__FILE__
d
=
$cellar
.
parent
+
'bin'
d
.
mkpath
unless
d
.
exist?
Dir
.
chdir
d
Pathname
.
new
(
'brew'
).
make_symlink
Pathname
.
new
(
'../Cellar'
)
+
'homebrew'
+
'brew'
end
\ No newline at end of file
Library/Homebrew/env.rb
浏览文件 @
fb5aefd4
...
...
@@ -21,4 +21,97 @@ $root=Pathname.new(__FILE__).dirname.parent.parent.realpath
$formula
=
$root
+
'Library'
+
'Formula'
$cellar
=
$root
+
'Cellar'
HOMEBREW_VERSION
=
'0.2'
\ No newline at end of file
HOMEBREW_VERSION
=
'0.3'
HOMEBREW_CACHE
=
File
.
expand_path
"~/Library/Caches/Homebrew"
######################################################################## utils
def
ohai
title
n
=
`tput cols`
.
strip
.
to_i
-
4
puts
"
\033
[0;34m==>
\033
[0;0;1m
#{
title
[
0
,
n
]
}
\033
[0;0m"
end
############################################################### class Pathname
# we enhance Pathname to make our code more legible
# of course this kind of thing is evil, but meh
class
Pathname
def
mv
dst
FileUtils
.
mv
to_s
,
dst
end
def
rename
dst
dst
=
Pathname
.
new
dst
dst
.
unlink
if
dst
.
exist?
mv
dst
end
def
install
src
if
src
.
is_a?
Array
src
.
each
{
|
src
|
install
src
}
elsif
File
.
exist?
src
mkpath
if
File
.
symlink?
src
# we use the BSD mv command because FileUtils copies the target and
# not the link! I'm beginning to wish I'd used Python quite honestly!
`mv
#{
src
}
#{
to_s
}
`
else
# we mv when possible as it is faster and you should only be using
# this function when installing from the temporary build directory
FileUtils
.
mv
src
,
to_s
end
end
end
def
cp
dst
if
file?
FileUtils
.
cp
to_s
,
dst
else
FileUtils
.
cp_r
to_s
,
dst
end
end
# extended to support the double extensions .tar.gz and .tar.bz2
def
extname
/(\.tar\.(gz|bz2))$/
.
match
to_s
return
$1
if
$1
return
File
.
extname
(
to_s
)
end
# for filetypes we support, basename without extension
def
stem
return
File
.
basename
(
to_s
,
extname
)
end
def
version
# eg. boost_1_39_0
/((\d+_)+\d+)$/
.
match
stem
return
$1
.
gsub
(
'_'
,
'.'
)
if
$1
# eg. foobar-4.5.1-1
/-((\d+\.)*\d+-\d+)$/
.
match
stem
return
$1
if
$1
# eg. foobar-4.5.1
/-((\d+\.)*\d+)$/
.
match
stem
return
$1
if
$1
# eg. foobar-4.5.1b
/-((\d+\.)*\d+([abc]|rc\d))$/
.
match
stem
return
$1
if
$1
# eg foobar-4.5.0-beta1
/-((\d+\.)*\d+-beta\d+)$/
.
match
stem
return
$1
if
$1
# eg. foobar4.5.1
/((\d+\.)*\d+)$/
.
match
stem
return
$1
if
$1
# eg. otp_src_R13B (this is erlang's style)
# eg. astyle_1.23_macosx.tar.gz
stem
.
scan
/_([^_]+)/
do
|
match
|
return
match
.
first
if
/\d/
.
match
$1
end
end
end
Library/Homebrew/formula.rb
0 → 100644
浏览文件 @
fb5aefd4
# Copyright 2009 Max Howell <max@methylblue.com>
#
# This file is part of Homebrew.
#
# Homebrew is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Homebrew is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Homebrew. If not, see <http://www.gnu.org/licenses/>.
require
'env'
class
BuildError
<
RuntimeError
def
initialize
cmd
super
"Build failed during:
#{
cmd
}
"
end
end
# the base class variety of formula, you don't get a prefix, so it's not really
# useful. See the derived classes for fun and games.
class
AbstractFormula
require
'find'
require
'fileutils'
# fuck knows, ruby is weird
# TODO please fix!
def
self
.
url
@url
end
def
url
self
.
class
.
url
end
def
self
.
md5
@md5
end
def
md5
self
.
class
.
md5
end
def
self
.
homepage
@homepage
end
def
homepage
self
.
class
.
homepage
end
# end ruby is weird section
def
version
@version
end
def
name
@name
end
# if the dir is there, but it's empty we consider it not installed
def
installed?
return
prefix
.
children
.
count
>
0
rescue
return
false
end
def
initialize
name
=
nil
@name
=
name
# fuck knows, ruby is weird
@url
=
url
if
@url
.
nil?
raise
"@url.nil?"
if
@url
.
nil?
@md5
=
md5
if
@md5
.
nil?
# end ruby is weird section
end
public
def
prefix
raise
"@name.nil!"
if
@name
.
nil?
raise
"@version.nil?"
if
@version
.
nil?
$cellar
+
@name
+
@version
end
def
bin
prefix
+
'bin'
end
def
doc
prefix
+
'share'
+
'doc'
+
name
end
def
man
prefix
+
'share'
+
'man'
end
def
man1
man
+
'man1'
end
def
lib
prefix
+
'lib'
end
def
include
prefix
+
'include'
end
def
caveats
nil
end
# Pretty titles the command and buffers stdout/stderr
# Throws if there's an error
def
system
cmd
ohai
cmd
if
ARGV
.
include?
'--verbose'
Kernel
.
system
cmd
else
out
=
''
IO
.
popen
"
#{
cmd
}
2>&1"
do
|
f
|
until
f
.
eof?
out
+=
f
.
gets
end
end
puts
out
unless
$?
==
0
end
raise
BuildError
.
new
(
cmd
)
unless
$?
==
0
end
# yields self with current working directory set to the uncompressed tarball
def
brew
ohai
"Downloading
#{
@url
}
"
FileUtils
.
mkpath
HOMEBREW_CACHE
Dir
.
chdir
HOMEBREW_CACHE
do
tmp
=
tgz
=
nil
begin
tgz
=
Pathname
.
new
(
fetch
()).
realpath
md5
=
`md5 -q "
#{
tgz
}
"`
.
strip
raise
"MD5 mismatch:
#{
md5
}
"
unless
@md5
and
md5
==
@md5
.
downcase
# we make an additional subdirectory so know exactly what we are
# recursively deleting later
# we use mktemp rather than appsupport/blah because some build scripts
# can't handle being built in a directory with spaces in it :P
tmp
=
`mktemp -dt
#{
File
.
basename
@url
}
`
.
strip
Dir
.
chdir
tmp
do
Dir
.
chdir
uncompress
(
tgz
)
do
yield
self
end
end
rescue
Interrupt
,
RuntimeError
if
ARGV
.
include?
'--debug'
# debug mode allows the packager to intercept a failed build and
# investigate the problems
puts
"Rescued build at:
#{
tmp
}
"
exit!
1
else
raise
end
ensure
FileUtils
.
rm_rf
tmp
if
tmp
end
end
end
protected
# returns the directory where the archive was uncompressed
# in this Abstract case we assume there is no archive
def
uncompress
path
path
.
dirname
end
private
def
fetch
%r[http://(www.)?github.com/.*/(zip|tar)ball/]
.
match
@url
if
$2
# curl doesn't do the redirect magic that we would like, so we get a
# stupidly named file, this is why wget would be beter, but oh well
tgz
=
"
#{
@name
}
-
#{
@version
}
.
#{
$2
==
'tar'
?
'tgz'
:
$2
}
"
oarg
=
"-o
#{
tgz
}
"
else
oarg
=
'-O'
#use the filename that curl gets
tgz
=
File
.
expand_path
File
.
basename
(
@url
)
end
agent
=
"Homebrew
#{
HOMEBREW_VERSION
}
(Ruby
#{
VERSION
}
; Mac OS X 10.5 Leopard)"
unless
File
.
exists?
tgz
`curl -#LA "
#{
agent
}
"
#{
oarg
}
"
#{
@url
}
"`
raise
"Download failed"
unless
$?
==
0
else
puts
"File already downloaded and cached"
end
return
tgz
end
def
method_added
method
raise
'You cannot override Formula.brew'
if
method
==
'brew'
end
end
# somewhat useful, it'll raise if you call prefix, but it'll unpack a tar/zip
# for you, check the md5, and allow you to yield from brew
class
UnidentifiedFormula
<
AbstractFormula
def
initialize
name
=
nil
super
name
end
private
def
uncompress
(
path
)
if
path
.
extname
==
'.zip'
`unzip -qq "
#{
path
}
"`
else
`tar xf "
#{
path
}
"`
end
raise
"Compression tool failed"
if
$?
!=
0
entries
=
Dir
[
'*'
]
if
entries
.
nil?
or
entries
.
length
==
0
raise
"Empty tarball!"
elsif
entries
.
length
==
1
# if one dir enter it as that will be where the build is
entries
.
first
else
# if there's more than one dir, then this is the build directory already
Dir
.
pwd
end
end
end
# this is what you will mostly use, reimplement install, prefix won't raise
class
Formula
<
UnidentifiedFormula
def
initialize
name
super
name
@version
=
Pathname
.
new
(
@url
).
version
unless
@version
end
def
self
.
class
name
#remove invalid characters and camelcase
name
.
capitalize
.
gsub
(
/[-_\s]([a-zA-Z0-9])/
)
{
$1
.
upcase
}
end
def
self
.
path
name
$formula
+
(
name
.
downcase
+
'.rb'
)
end
def
self
.
create
name
require
Formula
.
path
(
name
)
return
eval
(
Formula
.
class
(
name
)).
new
(
name
)
rescue
raise
"No formula for
#{
name
}
"
end
end
# see ack.rb for an example usage
class
ScriptFileFormula
<
AbstractFormula
def
install
bin
.
install
name
end
end
class
GithubGistFormula
<
ScriptFileFormula
def
initialize
super
File
.
basename
(
url
)
@version
=
File
.
basename
(
File
.
dirname
(
url
))[
0
,
6
]
end
end
Library/Homebrew/keg.rb
0 → 100644
浏览文件 @
fb5aefd4
# Copyright 2009 Max Howell <max@methylblue.com>
#
# This file is part of Homebrew.
#
# Homebrew is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Homebrew is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Homebrew. If not, see <http://www.gnu.org/licenses/>.
require
'env'
require
'formula'
class
Keg
attr_reader
:path
,
:version
,
:name
def
initialize
formula
if
formula
.
is_a?
AbstractFormula
@path
=
formula
.
prefix
@name
=
formula
.
name
@version
=
formula
.
version
elsif
formula
.
is_a?
Pathname
# TODO
elsif
formula
.
is_a?
String
kids
=
(
$cellar
+
formula
).
children
raise
"Multiple versions installed"
if
kids
.
length
>
1
@path
=
kids
[
0
]
@name
=
formula
@version
=
@path
.
basename
end
end
def
clean
# TODO unset write permission more
%w[bin lib]
.
each
{
|
d
|
(
Pathname
.
new
(
path
)
+
d
).
find
do
|
path
|
if
not
path
.
file?
next
elsif
path
.
extname
==
'.la'
# .la files are stupid
path
.
unlink
else
fo
=
`file -h
#{
path
}
`
args
=
nil
perms
=
0444
if
fo
=~
/Mach-O dynamically linked shared library/
args
=
'-SxX'
elsif
fo
=~
/Mach-O executable/
# defaults strip everything
args
=
''
# still do the strip
perms
=
0544
elsif
fo
=~
/script text executable/
perms
=
0544
end
if
args
puts
"Stripping:
#{
path
}
"
if
ARGV
.
include?
'--verbose'
path
.
chmod
0644
# so we can strip
unless
path
.
stat
.
nlink
>
1
`strip
#{
args
}
#{
path
}
`
else
# strip unlinks the file and recreates it, thus breaking hard links!
# is this expected behaviour? patch does it too… still,mktm this fixes it
tmp
=
`mktemp -t
#{
path
.
basename
}
`
.
strip
`strip -o
#{
tmp
}
#{
path
}
`
`cat
#{
tmp
}
>
#{
path
}
`
File
.
unlink
tmp
end
end
path
.
chmod
perms
end
end
}
# remove empty directories TODO Rubyize!
`perl -MFile::Find -e"finddepth(sub{rmdir},'
#{
path
}
')"`
end
def
rm
if
path
.
directory?
FileUtils
.
chmod_R
0777
,
path
# ensure we have permission to delete
path
.
rmtree
end
end
private
def
__symlink_relative_to
from
,
to
tod
=
to
.
dirname
tod
.
mkpath
Dir
.
chdir
(
tod
)
do
#TODO use Ruby function so we get exceptions
#NOTE Ruby functions are fucked up!
`ln -sf "
#{
from
.
relative_path_from
tod
}
"`
@n
+=
1
end
end
# symlinks a directory recursively into our FHS tree
def
__ln
start
start
=
path
+
start
return
unless
start
.
directory?
start
.
find
do
|
from
|
next
if
from
==
start
prune
=
false
relative_path
=
from
.
relative_path_from
path
to
=
$root
+
relative_path
if
from
.
file?
__symlink_relative_to
from
,
to
elsif
from
.
directory?
# no need to put .app bundles in the path, the user can just use
# spotlight, or the open command and actual mac apps use an equivalent
Find
.
prune
if
from
.
extname
.
to_s
==
'.app'
branch
=
from
.
relative_path_from
start
case
yield
branch
when
:skip
Find
.
prune
when
:mkpath
to
.
mkpath
@n
+=
1
else
__symlink_relative_to
from
,
to
Find
.
prune
end
end
end
end
public
def
ln
# yeah indeed, you have to force anything you need in the main tree into
# these dirs REMEMBER that *NOT* everything needs to be in the main tree
# TODO consider using hardlinks
@n
=
0
__ln
(
'etc'
)
{
:mkpath
}
__ln
(
'bin'
)
{
:link
}
__ln
(
'lib'
)
{
|
path
|
:mkpath
if
[
'pkgconfig'
,
'php'
].
include?
path
.
to_s
}
__ln
(
'include'
)
{
:link
}
mkpaths
=
(
1
..
9
).
collect
{
|
x
|
"man/man
#{
x
}
"
}
<<
'man'
<<
'doc'
<<
'locale'
<<
'info'
<<
'aclocal'
__ln('share') {|path| :mkpath if mkpaths.include? path.to_s}
return @n
end
end
\ No newline at end of file
Library/Homebrew/unittest.rb
浏览文件 @
fb5aefd4
...
...
@@ -2,7 +2,7 @@
$:
.
unshift
File
.
dirname
(
__FILE__
)
require
'test/unit'
require
'
brewkit
'
require
'
formula
'
require
'stringio'
class
TestFormula
<
Formula
...
...
README
浏览文件 @
fb5aefd4
Homebrew
========
Homebrew's purpose is
the same as MacPorts or Fink, ie. to let you easily
install other open source software on your Mac.
Homebrew
's purpose is
basically the same as MacPorts or Fink, ie. to let you
easily
install other open source software on your Mac.
Here'
s
why
you
may
prefer
Homebrew
to
the
alternatives
:
...
...
@@ -34,30 +34,43 @@ Here's why you may prefer Homebrew to the alternatives:
Homebrew
will
automatically
open
it
for
you
to
tweak
with
TextMate
or
$
EDITOR
.
Or skip going via a package entirely, just install into the Cellar and use
"brew ln" to symlink it into the main tree.
6.
DIY
package
installation
MacPorts
doesn
't support the beta version? Need an older version? Need
custom compile flags? The Homebrew toolchain is carefully segregated so
you can just build your own stuff while still reaping the benefits of
package management.
6. Optimisation
Just install to the Cellar and then call brew ln to symlink that
installation into /usr/local, eg.
./configure --prefix=/usr/local/Cellar/wget/1.10
make install
brew ln wget
This means you can also install multiple versions of the same package and
switch on demand.
7. Optimisation
We optimise for Leopard Intel, binaries are stripped, compile flags
tweaked. Nobody wants crappy, slow software. Apart from MacPorts and Fink.
7
. Integration with existing OS X technologies
8
. Integration with existing OS X technologies
Homebrew integrates with Ruby gems, CPAN and Python disttools. These tools
exist already and do the job great. We don'
t
reinvent
the
wheel
,
we
just
improve
it
by
making
these
tools
install
with
more
management
options
.
8
. Complimenting what OS X already has
9
.
Complimenting
what
OS
X
already
has
Macports
is
an
autarky
.
You
get
a
duplicate
copy
of
libz
,
OpenSSL
,
Python
etc
.
They
do
this
to
support
OS
X
Tiger
,
etc
.
more
easily
.
We
don
't support
Tiger, we duplicate nothing. Homebrew compliments OS X, it doesn'
t
seek
to
operate
independently
of
it
.
9
. Homebrew has a beer theme
A
.
Homebrew
has
a
beer
theme
Beer
goggles
will
help
you
to
evangelise
Homebrew
more
effectively
.
X. Homebrew helps you get
chicks
B
.
Homebrew
helps
get
you
chicks
There
's no conclusive scientific evidence as yet, but I firmly believe it'
s
just a matter of
statistics and time
.
just
a
matter
of
time
and
statistics
.
I
know
I
've made it sound so awesome you can hardly wait to rip MacPorts out
and embrace the fresh hoppy taste of Homebrew, but I should point out that it
...
...
bin/brew
浏览文件 @
fb5aefd4
...
...
@@ -8,6 +8,7 @@ require 'env'
# often causes Ruby to throw exception ffs
Dir
.
chdir
'/'
unless
File
.
directory?
ENV
[
'PWD'
]
######################################################################## funcs
def
prune
n
=
0
dirs
=
Array
.
new
...
...
@@ -37,130 +38,113 @@ def prune
return n
end
def formulize name
name=Pathname.new name
return name if name.directory? and name.parent.realpath == $cellar
return File.basename(name, '.rb') if name.file? and name.extname == '.rb' and name.parent.realpath == $formula
name=name.to_s
raise "
#{
name
}
is an invalid name for a formula" if name.include? '/'
return name if ($formula+(name+'.rb')).file?
return name if ($cellar+name).directory?
raise "No formula or keg for
#{
name
}
found"
end
def shift_formulae_from_ARGV
fae=Array.new
i=0
while name=ARGV[i]
unless name[0,1] == '-'
fae<<formulize(ARGV.shift).to_s
# we actually remove formulae from ARGV so that any other analysis of ARGV
# only includes relevent arguments
# TODO require will throw if no formula, so we should catch no?
def extract_named_args
args=Array.new
ARGV.delete_if do |arg|
if arg[0,1] == '-'
false
else
i+=1
args<<arg
true
end
end
raise "You must specify a formula" if fae.empty?
return fae
end
def __class name
#remove invalid characters and camelcase
name.capitalize.gsub(/[-_
\s
]([a-zA-Z0-9])/) { $1.upcase }
end
def __rb name
$formula+(name+'.rb')
return args
end
def __obj name
require "
#{
__rb
name
}
"
return eval(__class(name)).new(name)
def extract_kegs
require 'keg'
kegs=extract_named_args.collect {|name| Keg.new name}
raise "Expecting the name of a keg or formula, eg:
\n\t
brew
#{
ARGV
.
join
' '
}
wget" if kegs.empty?
return kegs
end
def rm keg
#TODO if multiple versions don't rm all unless --force
path=$cellar+keg
`chmod -R u+rw
#{
path
}
` # we leave things read only
path.rmtree
puts "
#{
path
}
removed (
#{
prune
}
files)"
def abv keg=nil
path=keg ? keg.path : $cellar
if path.directory?
`find
#{
path
}
-type f | wc -l`.strip+' files, '+`du -hd0
#{
path
}
| cut -d"
\t
" -f1`.strip
else
nil
end
end
def ln name
keg=$cellar+name
keg=keg.realpath
if keg.parent.parent == $root
# we are one dir too high
kids=keg.children
raise "
#{
keg
}
is empty :(" if kids.length == 0
raise "There are multiple versions of
#{
keg
.
basename
}
installed please specify one" if kids.length > 1
keg=keg.children.first
raise "
#{
keg
}
is not a directory" unless keg.directory?
elsif keg.parent.parent.parent != $root
raise '
#{
keg
}
is not a keg'
def install formula
require 'keg'
raise "
#{
formula
.
name
}
already installed!
\n\t
#{
formula
.
prefix
}
" if formula.installed?
beginning = Time.now
formula.brew do
if ARGV.include? '--interactive'
ohai "Entering interactive mode"
puts "Type `exit' to return and finalize the installation"
puts "Install to this prefix:
#{
formula
.
prefix
}
"
pid=fork
if pid.nil?
exec 'bash'
else
Process.wait pid
end
elsif ARGV.include? '--help'
ohai './configure --help'
puts `./configure --help`
exit
else
formula.prefix.mkpath
formula.install
%w[README ChangeLog COPYING COPYRIGHT AUTHORS].each do |file|
formula.prefix.install file if File.file? file
end
end
end
# yeah indeed, you have to force anything you need in the main tree into
# these directories :P
# NOTE that not everything needs to be in the main tree
# TODO consider using hardlinks
$n=0
lnd(keg, 'etc') {:mkdir}
lnd(keg, 'include') {:link}
lnd(keg, 'bin') {:link}
lnd(keg, 'lib') {|path| :mkpath if ['pkgconfig','php'].include? path.to_s}
lnd(keg, 'share') do |path|
mkpaths=(1..9).collect {|x| "man/man
#{
x
}
"} <<'man'<<'doc'<<'locale'<<'info'<<'aclocal'
:mkpath if mkpaths.include? path.to_s
ohai 'Finishing up'
keg=Keg.new formula
keg.clean
keg.ln
if formula.caveats
ohai "Caveats"
puts formula.caveats
ohai "Summary"
end
return $n
puts "
#{
keg
.
path
}
: "+abv(keg)+", built in
#{
pretty_duration
Time
.
now
-
beginning
}
"
rescue Exception
formula.prefix.rmtree
raise
end
def symlink_relative_to from, to
tod=to.dirname
tod.mkpath
Dir.chdir(tod) do
#TODO use ruby function so we get exceptions
`ln -sf "
#{
from
.
relative_path_from
tod
}
"`
$n+=1
end
def mk url
require 'formula'
path=Pathname.new(url)
/(.*?)[-_.]?
#{
path
.
version
}
/.match path.basename
raise "Couldn't parse name from
#{
url
}
" if $1.nil? or $1.empty?
path=Formula.path $1
raise "
#{
path
}
already exists!" if File.exist? path
f=File.new path, 'w'
f.puts "require 'brewkit'"
f.puts
f.puts "class
#{
Formula
.
class
$1
}
<Formula"
f.puts " @url='
#{
url
}
'"
f.puts " @homepage=''" # second because you fill in these two first
f.puts " @md5=''"
f.puts
f.puts " def install"
f.puts " system
\"
./configure --disable-debug --prefix='
\#
{prefix}'
\"
"
f.puts " system
\"
make install
\"
"
f.puts " end"
f.print "end"
f.close
return path
end
# symlinks a directory recursively into our FHS tree
def lnd keg, start
start=keg+start
return unless start.directory?
start.find do |from|
next if from == start
prune=false
relative_path=from.relative_path_from keg
to=$root+relative_path
if from.directory?
# no need to put .app bundles in the path, the user can just use
# spotlight, or the open command and actual mac apps use an equivalent
Find.prune if from.extname.to_s == '.app'
cmd=yield from.relative_path_from(start)
if :skip == cmd
Find.prune
elsif :mkpath == cmd
to.mkpath
$n+=1
else
symlink_relative_to from, to
Find.prune
end
elsif from.file?
symlink_relative_to from, to
end
end
def prefix
Pathname.new(__FILE__).dirname.parent.expand_path
end
def usage
...
...
@@ -181,11 +165,6 @@ Commands:
EOS
end
def abv keg=''
keg=$cellar+keg
return nil if not File.directory? keg
`find
#{
keg
}
-type f | wc -l`.strip+' files, '+`du -hd0
#{
keg
}
| cut -d"
\t
" -f1`.strip
end
######################################################################## utils
def pretty_duration s
...
...
@@ -197,147 +176,80 @@ end
######################################################################### impl
begin
case ARGV.shift
when 'prune'
puts "Pruned
#{
prune
}
files"
when '--prefix'
# we use the cwd because __FILE__ can be relative and expand_path
# resolves the symlink for the working directory if fed a relative path
# NOTE we don't use Dir.pwd because it resolves the symlink :(
cwd=Pathname.new `pwd`.strip
puts File.expand_path(cwd+__FILE__+'../../')
when '--cache'
puts File.expand_path('~/Library/Application Support/Homebrew')
when '-h', '--help', '--usage', '-?'
puts usage
when '-v', '--version'
puts HOMEBREW_VERSION
when 'list'
fae=shift_formulae_from_ARGV.collect do |name|
keg=$cellar+name
keg.directory? ? keg : nil
end
raise 'No such keg' if fae.first.nil? and fae.length == 1
puts `find
#{
fae
.
join
' '
}
-type f -print`
when 'macports'
exec "open 'http://www.macports.org/ports.php?by=name&substr=
#{
ARGV
.
shift
}
'"
when '--prefix' then puts prefix
when '--cache' then puts Homebrew::cache
when '-h', '--help', '--usage', '-?' then puts usage
when '-v', '--version' then puts HOMEBREW_VERSION
when 'macports' then exec "open 'http://www.macports.org/ports.php?by=name&substr=
#{
ARGV
.
shift
}
'"
when 'ls', 'list'
dirs=extract_kegs.collect {|keg| keg.path}
exec "find
#{
dirs
.
join
' '
}
-not -type d -print"
when 'edit'
if ARGV.empty?
exec "mate
#{
$formula
}
#{
$root
}
/Library/Homebrew
#{
$root
}
/bin/brew
#{
$root
}
/README"
else
exec "mate
#{
$formula
}
/
#{
ARGV
.
shift
}
.rb"
paths=extract_kegs.collect {|keg| keg.formula_path.to_s.gsub ' ', '
\\
'}
exec "mate
#{
paths
.
join
' '
}
"
end
when 'install'
shift_formulae_from_ARGV.each do |name|
beginning = Time.now
o=__obj(name)
begin
raise "
#{
o
.
prefix
}
already exists!" if o.prefix.exist?
o.brew do
if ARGV.include? '--interactive'
ohai "Entering interactive mode, type `exit' to return to finalize installation"
puts "Install to this prefix:
#{
o
.
prefix
}
"
pid=fork
if pid.nil?
exec 'bash'
else
Process.wait pid
end
elsif ARGV.include? '--help'
ohai './configure --help'
puts `./configure --help`
exit
else
o.prefix.mkpath
o.install
%w[README ChangeLog COPYING COPYRIGHT AUTHORS].each do |file|
FileUtils.cp file, o.prefix if File.file? file
end
#this is common, and we don't want it
versioned_docs=o.doc.parent+"
#{
o
.
name
}
-
#{
o
.
version
}
"
versioned_docs.rename o.doc if versioned_docs.exist?
end
end
ohai 'Finishing up'
o.clean
ln name
if o.caveats
ohai "Caveats"
puts o.caveats
ohai "Summary"
end
puts "
#{
o
.
prefix
}
: "+abv(name)+", built in
#{
pretty_duration
Time
.
now
-
beginning
}
"
rescue Exception
FileUtils.rm_rf o.prefix
raise
end
require 'formula'
extract_named_args.each do |name|
install Formula.create(name)
end
when 'ln'
when 'ln'
, 'link'
n=0
shift_formulae_from_ARGV.each {|name| n+=ln name}
(kegs=extract_kegs).each do |keg|
n+=nn=keg.ln
puts "Created
#{
nn
}
links for
#{
keg
.
name
}
" if kegs.length > 1
end
puts "Created
#{
n
}
links"
when 'rm', 'uninstall'
shift_formulae_from_ARGV.each {|name| rm name}
when 'mk'
require 'brewkit'
url=ARGV.shift
version=extract_version File.basename(url, Pathname.new(url).extname)
/(.*?)[-_.]?
#{
version
}
/.match File.basename(url)
raise "Couldn't parse name from
#{
url
}
" if $1.nil? or $1.empty?
path=$formula+($1.downcase+'.rb')
raise "
#{
path
}
already exists!" if File.exist? path
f=File.new path, 'w'
f.puts "require 'brewkit'"
f.puts
f.puts "class
#{
__class
$1
}
<Formula"
f.puts " @url='
#{
url
}
'"
f.puts " @homepage=''" # second because you fill in these two first
f.puts " @md5=''"
f.puts
f.puts " def install"
f.puts " system
\"
./configure --disable-debug --prefix='
\#
{prefix}'
\"
"
f.puts " system
\"
make install
\"
"
f.puts " end"
f.print "end"
f.close
extract_kegs.each do |keg|
puts "Removing
#{
keg
.
name
}
..."
keg.rm
end
print "Pruning
#{
prefix
}
/..."
puts "
#{
prune
}
symbolic links pruned"
if Kernel.system "which mate > /dev/null" and $? == 0
exec "mate
#{
path
}
"
when 'prune'
puts "Pruned
#{
prune
}
symbolic links"
when 'mk', 'make'
paths=ARGV.collect {|arg| mk arg}
if paths.empty?
raise "Invalid URL"
elsif Kernel.system "which mate > /dev/null" and $? == 0
paths=paths.collect {|path| path.to_s.gsub " ", "
\\
"}
exec "mate
#{
paths
.
join
' '
}
"
else
puts path
puts path
s.join("
\n
")
end
when 'info','abv'
when 'info',
'abv'
if ARGV.empty?
puts abv
elsif ARGV[0][0..6] == 'http://'
puts Pathname.new(ARGV.shift).version
else
if ARGV[0][0..6] == 'http://'
require 'brewkit'
path=Pathname.new ARGV[0]
basename=File.basename path, path.extname
v=extract_version basename
puts v
else
o=__obj shift_formulae_from_ARGV[0]
puts "
#{
o
.
name
}
#{
o
.
version
}
"
puts o.homepage
if abv=abv(o.name)
ohai "Installation"
puts abv
end
if o.caveats
ohai 'Caveats'
puts o.caveats
end
#TODO show outdated status and that
keg=extract_kegs[0]
frm=Formula.create keg.name
puts "
#{
keg
.
name
}
#{
keg
.
version
}
"
puts frm.homepage
if keg.installed?
puts "
#{
abv
keg
}
(installed to
#{
keg
.
path
}
)"
end
if frm.caveats
ohai 'Caveats'
puts frm.caveats
end
end
else
puts usage
end
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录