{
$Build::Simple::VERSION
=
'0.002'
;
}
has
_nodes
=> (
is
=>
'ro'
,
default
=>
sub
{ {} },
);
sub
_get_node {
my
(
$self
,
$key
) =
@_
;
return
$self
->_nodes->{
$key
};
}
sub
has_node {
my
(
$self
,
$key
) =
@_
;
return
exists
$self
->_nodes->{
$key
};
}
sub
add_file {
my
(
$self
,
$name
,
%args
) =
@_
;
Carp::croak(
"File '$name' already exists in database"
)
if
!
$args
{
override
} &&
$self
->_get_node(
$name
);
my
$node
= Build::Simple::Node->new(
%args
,
phony
=> 0);
$self
->_nodes->{
$name
} =
$node
;
push
@{
$self
->_get_node(
$_
)->dependencies },
$name
for
@{
$args
{dependents} };
return
;
}
sub
add_phony {
my
(
$self
,
$name
,
%args
) =
@_
;
Carp::croak(
"Phony '$name' already exists in database"
)
if
!
$args
{
override
} &&
$self
->_get_node(
$name
);
my
$node
= Build::Simple::Node->new(
%args
,
phony
=> 1);
$self
->_nodes->{
$name
} =
$node
;
push
@{
$self
->_get_node(
$_
)->dependencies },
$name
for
@{
$args
{dependents} };
return
;
}
sub
_node_sorter {
my
(
$self
,
$current
,
$callback
,
$seen
,
$loop
) =
@_
;
Carp::croak(
"$current has a circular dependency, aborting!\n"
)
if
exists
$loop
->{
$current
};
return
if
$seen
->{
$current
}++;
my
$node
=
$self
->_get_node(
$current
) or Carp::croak(
"Node $current doesn't exist"
);
local
$loop
->{
$current
} = 1;
$self
->_node_sorter(
$_
,
$callback
,
$seen
,
$loop
)
for
@{
$node
->dependencies };
$callback
->(
$current
,
$node
);
return
;
}
sub
_sort_nodes {
my
(
$self
,
$startpoint
) =
@_
;
my
@ret
;
$self
->_node_sorter(
$startpoint
,
sub
{
push
@ret
,
$_
[0] }, {}, {});
return
@ret
;
}
sub
_is_phony {
my
(
$self
,
$key
) =
@_
;
my
$node
=
$self
->_get_node(
$key
);
return
$node
?
$node
->phony : 0;
}
sub
run {
my
(
$self
,
$startpoint
,
%options
) =
@_
;
$self
->_node_sorter(
$startpoint
,
sub
{
$_
[1]->run(
$_
[0],
$self
, \
%options
) }, {}, {});
return
;
}
1;