my
$TREE
;
sub
description_of {
local
$" =
', '
;
no
warnings
'uninitialized'
;
my
@desc
;
for
my
$v
(
@_
) {
push
@desc
,
!
defined
$v
?
'<undef>'
:
$v
eq
''
?
"''"
:
ref
$v
eq
'ARRAY'
?
"[ @$v ]"
:
ref
$v
eq
'HASH'
?
"{ @{[map{qq'$_ => $v->{$_}'}sort keys%$v]} }"
:
$v
;
}
return
"@desc"
;
}
sub
create_repository {
my
(
$dir
) =
@_
;
mkpath
$dir
;
Git::Repository->run(
'init'
, {
cwd
=>
$dir
} );
my
$r
= Git::Repository->new(
work_tree
=>
$dir
, {
quiet
=> 1 } );
$r
->run(
qw( config user.email test@example.com )
);
$r
->run(
qw( config user.name Test )
);
$TREE
=
$r
->run(
mktree
=> {
input
=>
''
} );
return
$r
;
}
sub
describe_repository {
my
(
$r
) =
@_
;
my
%log
;
my
@commits
;
my
(
%head
,
%tag
);
do
{
my
(
$h
,
$p
,
$log
) =
split
/-/,
$_
, 3;
$log
{
$h
} =
$log
;
$p
=~ y/ //d;
push
@commits
,
$p
?
"$log-$p"
:
$log
;
}
for
$r
->run(
qw( log --pretty=format:%H-%P-%s --date-order --all )
);
%head
=
reverse
map
{ s{ refs/heads/}{ };
split
/ / }
$r
->run(
'show-ref'
,
'--heads'
);
%tag
=
reverse
map
{ s{ refs/tags/}{ };
split
/ / }
$r
->run(
'show-ref'
,
'--tags'
);
my
%atag
;
for
my
$tag
(
keys
%tag
) {
if
(
my
@tag
=
eval
{
$r
->run(
'cat-file'
,
tag
=>
$tag
) } ) {
my
(
$commit
) = (
split
/ /,
$tag
[0] )[-1];
$atag
{
$tag
} = [
$commit
,
$tag
[-1] ];
delete
$tag
{
$tag
};
}
}
my
$refs
=
join
' '
,
sort
map
(
"$_=$log{$head{$_}}"
,
keys
%head
),
map
(
"$_:$atag{$_}[1]>$log{$atag{$_}[0]}"
,
keys
%atag
),
map
(
"$_>$log{$tag{$_}}"
,
keys
%tag
);
my
$desc
=
join
' '
,
reverse
@commits
;
$desc
=~ s/([a-f0-9]{40})/
$log
{$1}/g;
return
wantarray
? (
$desc
,
$refs
) :
$desc
;
}
sub
build_repositories {
my
(
$commits
,
$refs
,
$dir
) =
@_
;
$dir
||= tempdir(
CLEANUP
=> 1 );
my
$now
=
time
;
my
(
%r
,
%sha
);
for
my
$commit
(
split
/ /,
$commits
) {
my
(
$child
,
$parent
) =
split
/-/,
$commit
;
my
(
$name
) =
$child
=~ /^([A-Z]+)/g;
my
@parents
=
$parent
=~ /([A-Z]+\d+)/g
if
$parent
;
my
$r
=
$r
{
$name
} ||= create_repository(
File::Spec->rel2abs( File::Spec->catfile(
$dir
,
$name
) ) );
$now
++;
$sha
{
$child
} =
$r
->run(
'commit-tree'
=>
$TREE
,
{
input
=>
$child
,
env
=> {
GIT_AUTHOR_DATE
=>
$now
,
GIT_COMMITTER_DATE
=>
$now
,
},
},
map
+(
'-p'
=>
$sha
{
$_
} ),
@parents
);
}
for
my
$ref
(
split
/ /,
$refs
) {
my
(
$name
,
$type
,
$commit
) =
split
/([>=])/,
$ref
;
my
(
$repo_name
) =
$commit
=~ /^([A-Z]+)/;
my
$r
=
$r
{
$repo_name
};
if
(
$type
eq
'='
) {
$r
->run(
'update-ref'
,
"refs/heads/$name"
,
$sha
{
$commit
} );
}
else
{
(
$name
,
my
$msg
) =
split
/:/,
$name
;
$r
->run(
tag
=> (
'-m'
=>
$msg
)x!!
$msg
,
$name
,
$sha
{
$commit
} );
}
}
return
values
%r
;
}
1;