#!/usr/bin/env perl
my
%option
= (
source
=>
'/opt/src/git'
,
destination
=>
'/opt/git'
,
limit
=> 0,
verbose
=> 0,
rc
=> 1,
);
GetOptions(
\
%option
,
'source=s'
,
'destination=s'
,
'verbose+'
,
'quiet'
,
'since=s'
,
'until=s'
,
'limit=i'
,
'force'
,
'list'
,
'missing'
,
'installed'
,
'rc!'
,
'fetch'
,
'test'
,
'docs'
,
'help'
,
'manual'
,
) or pod2usage(
-verbose
=> 0 );
pod2usage(
-verbose
=> 1 )
if
$option
{help};
pod2usage(
-verbose
=> 2 )
if
$option
{manual};
my
%run_opt
;
$option
{quiet} = 1
if
$option
{test};
$option
{verbose} = 0
if
$option
{quiet};
$run_opt
{stderr} =
undef
if
!
$option
{verbose};
$run_opt
{stdout} =
sub
{
print
shift
}
if
$option
{verbose} > 1;
my
$r
= Git::Repository->new(
work_tree
=>
$option
{source} );
$r
->run(
'fetch'
)
if
$option
{fetch};
my
%tag_for
=
map
{ (
my
$v
=
substr
$_
, 1 ) =~ y/-/./; (
$v
=>
$_
) }
grep
/^v[^0]/ && !/^v1\.0rc/,
$r
->run(
tag
=>
'-l'
,
'v*'
);
my
@versions
=
sort
cmp_git
@ARGV
?
@ARGV
:
keys
%tag_for
;
{
my
%alias
= (
'1.0.1'
=>
'1.0.0a'
,
'1.0.2'
=>
'1.0.0b'
,
);
my
%seen
;
@versions
=
grep
!
$seen
{
$_
}++,
map
$alias
{
$_
} ||
$_
,
@versions
;
}
@versions
=
grep
!/rc/,
@versions
if
!
$option
{rc};
@versions
=
grep
!is_installed(
$_
),
@versions
if
$option
{missing};
@versions
=
grep
is_installed(
$_
),
@versions
if
$option
{installed};
@versions
=
grep
cmp_git(
$option
{since},
$_
) <= 0,
@versions
if
$option
{since};
@versions
=
grep
cmp_git(
$_
,
$option
{
until
} ) <= 0,
@versions
if
$option
{
until
};
@versions
=
$option
{limit} > 0
?
@versions
[ -
$option
{limit} .. -1 ]
:
@versions
[ 0 .. -
$option
{limit} - 1 ]
if
$option
{limit};
my
@nope
=
grep
!
exists
$tag_for
{
$_
},
@versions
;
die
"Can't compile non-existent versions: @nope\n"
if
@nope
;
print
map
"$_\n"
,
@versions
and
exit
if
$option
{list};
if
(
$option
{test} ) {
import
Test::More;
plan(
tests
=>
scalar
@versions
);
$option
{destination} = tempdir(
CLEANUP
=> 1 );
}
chdir
$option
{source} or
die
"Can't chdir to $option{source}: $!"
;
for
my
$version
(
@versions
) {
if
( is_installed(
$version
) && !
$option
{force} ) {
print
"*** GIT $version ALREADY INSTALLED ***\n"
if
!
$option
{quiet};
next
;
}
else
{
print
"*** GIT $version ***\n"
if
!
$option
{quiet};
$r
->run(
checkout
=>
'-f'
,
'-q'
,
$tag_for
{
$version
} );
$r
->run(
clean
=>
'-xqdf'
);
if
(
cmp_git(
$version
,
'1.3.3'
) <= 0
&& cmp_git(
'1.1.0'
,
$version
) <= 0
&&
do
{
no
warnings; `git-describe`; $? != 0 }
)
{
local
( $^I,
@ARGV
) = (
''
,
'GIT-VERSION-GEN'
);
s/git-describe/git describe/,
print
while
<>;
}
if
( cmp_git(
$version
,
'1.0.9'
) == 0 ) {
local
( $^I,
@ARGV
) = (
''
,
'Makefile'
);
s/^GIT_VERSION = .*/GIT_VERSION =
$version
/,
print
while
<>;
}
elsif
( cmp_git(
$version
,
'1.7.5.rc0'
) <= 0
&& cmp_git(
'1.7.4.2'
,
$version
) <= 0 )
{
$r
->run(
'cherry-pick'
,
'-n'
,
'ebae9ff95de2d0b36b061c7db833df4f7e01a41d'
);
my
$version_file
= File::Spec->catfile(
$r
->work_tree,
'version'
);
open
my
$fh
,
'>'
,
$version_file
or
die
"Can't open $version_file: $!"
;
print
$fh
"$version\n"
;
}
my
$prefix
= File::Spec->catdir(
$option
{destination},
$version
);
my
@make
= (
make
=>
"prefix=$prefix"
);
local
$ENV
{PERL_MB_OPT};
local
$ENV
{PERL_MM_OPT};
remove_tree(
$prefix
)
if
-e
$prefix
;
run_cmd(
@make
=>
'-j3'
);
run_cmd(
@make
=>
'install'
);
run_cmd(
@make
=>
'install-doc'
)
if
$option
{docs};
if
(
$option
{test} ) {
ok( is_installed(
$version
),
"$version installed successfully"
);
remove_tree(
$prefix
);
}
}
}
sub
run_cmd {
print
"* @_\n"
if
!
$option
{quiet};
System::Command->loop_on(
command
=> \
@_
,
%run_opt
) or
die
"FAIL: @_\n"
;
}
sub
is_installed {
my
(
$version
) =
@_
;
my
$git
=
File::Spec->catfile(
$option
{destination},
$version
,
'bin'
,
'git'
);
return
eval
{ Git::Repository->version_eq(
$version
, {
git
=>
$git
} ) };
}