#!/bin/false
our
$VERSION
=
'0.1'
;
has
config
=> (
is
=>
'ro'
);
has
logger
=> (
is
=>
'ro'
,
default
=>
sub
{ App::Nrepo::Logger->new() } );
sub
go {
my
(
$self
,
$action
,
@args
) =
@_
;
$self
->_validate_config();
my
$dispatch
= {
'add-file'
=> \
&add_file
,
'del-file'
=> \
&del_file
,
'clean'
=> \
&clean
,
'init'
=> \
&init
,
'list'
=> \
&list
,
'mirror'
=> \
&mirror
,
'tag'
=> \
&tag
,
};
exists
$dispatch
->{
$action
}
||
$self
->logger->log_and_croak(
level
=>
'error'
,
message
=>
"ERROR: ${action} not supported."
);
$dispatch
->{
$action
}->(
$self
,
@args
);
exit
(0);
}
sub
_validate_config {
my
$self
=
shift
;
$self
->config->{
'data_dir'
} =
File::Spec->rel2abs(
$self
->config->{data_dir} );
$self
->logger->log_and_croak(
level
=>
'error'
,
message
=>
sprintf
"datadir does not exist: %s"
,
$self
->config->{data_dir},
)
unless
-d
$self
->config->{data_dir};
$self
->logger->log_and_croak(
level
=>
'error'
,
message
=>
sprintf
"Unknown tag_style %s, must be topdir or bottomdir\n"
,
$self
->config->{tag_style},
)
unless
$self
->config->{tag_style} =~ m/^(?:top|bottom)dir$/;
for
my
$repo
(
sort
keys
%{
$self
->config->{
'repo'
} } ) {
for
my
$param
(
qw/type local arch/
) {
$self
->logger->log_and_croak(
level
=>
'error'
,
message
=>
sprintf
"repo: %s missing param: %s"
,
$repo
,
$param
,
)
unless
$self
->config->{repo}->{
$repo
}->{
$param
};
if
(
$param
eq
'arch'
) {
my
$arch
=
$self
->config->{
'repo'
}->{
$repo
}->{
'arch'
};
my
$arches
=
ref
(
$arch
) eq
'ARRAY'
?
$arch
: [
$arch
];
$self
->config->{
'repo'
}->{
$repo
}->{
'arch'
} =
$arches
;
}
elsif
(
$param
eq
'type'
) {
unless
(
$self
->config->{repo}->{
$repo
}->{
$param
} eq
'Yum'
||
$self
->config->{repo}->{
$repo
}->{
$param
} eq
'Apt'
||
$self
->config->{repo}->{
$repo
}->{
$param
} eq
'Plain'
,
)
{
$self
->logger->log_and_croak(
level
=>
'error'
,
message
=>
sprintf
"repo: %s param: %s value: %s is not supported"
,
$repo
,
$param
,
$self
->config->{repo}->{
$repo
}->{
$param
},
);
}
}
}
}
}
sub
_get_plugin {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
type
=> {
type
=> SCALAR, },
options
=> {
options
=> HASHREF, },
}
);
my
$plugin
;
for
my
$p
(
Module::Pluggable::Object->new(
instantiate
=>
'new'
,
search_path
=> [
'App::Nrepo::Plugin'
],
except
=> [
'App::Nrepo::Plugin::Base'
],
)->plugins( %{
$o
{
'options'
} } )
)
{
$plugin
=
$p
if
$p
->type() eq
$o
{
'type'
};
}
$self
->logger->log_and_croak(
level
=>
'error'
,
message
=>
"Failed to find a plugin for type: $o{'type'}"
)
unless
$plugin
;
return
$plugin
;
}
sub
_get_repo_dir {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
repo
=> {
type
=> SCALAR },
tag
=> {
type
=> SCALAR,
default
=>
'head'
, },
}
);
my
$data_dir
=
$self
->config->{data_dir};
my
$tag_style
=
$self
->config->{tag_style};
my
$repo
=
$o
{
'repo'
};
my
$tag
=
$o
{
'tag'
};
my
$local
=
$self
->config->{
'repo'
}->{
$repo
}->{
'local'
};
if
(
$tag_style
eq
'topdir'
) {
return
File::Spec->catdir(
$data_dir
,
$tag
,
$local
);
}
elsif
(
$tag_style
eq
'bottomdir'
) {
return
File::Spec->catdir(
$data_dir
,
$local
,
$tag
);
}
else
{
$self
->logger->log_and_croak(
level
=>
'error'
,
message
=>
'_get_repo_dir: Unknown tag_style: '
.
$tag_style
);
}
}
sub
add_file {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
'repo'
=> {
type
=> SCALAR },
'arch'
=> {
type
=> SCALAR },
'file'
=> {
type
=> SCALAR | ARRAYREF },
'force'
=> {
type
=> BOOLEAN,
default
=> 0 },
},
);
my
$options
= {
repo
=>
$o
{
'repo'
},
arches
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'arch'
},
backend
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
} ),
force
=>
$o
{
'force'
},
};
my
$plugin
=
$self
->_get_plugin(
type
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
options
=>
$options
,
);
$plugin
->add_file(
$o
{
'arch'
},
$o
{
'file'
} );
}
sub
del_file {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
'repo'
=> {
type
=> SCALAR },
'arch'
=> {
type
=> SCALAR },
'file'
=> {
type
=> SCALAR | ARRAYREF },
},
);
my
$options
= {
repo
=>
$o
{
'repo'
},
arches
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'arch'
},
backend
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
} ),
force
=>
$o
{
'force'
},
};
my
$plugin
=
$self
->_get_plugin(
type
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
options
=>
$options
,
);
$plugin
->del_file(
$o
{
'arch'
},
$o
{
'file'
} );
}
sub
clean {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
repo
=> {
type
=> SCALAR, },
arch
=> {
type
=> SCALAR,
optional
=> 1 },
force
=> {
type
=> BOOLEAN,
optional
=> 1, },
}
);
if
(
$o
{
'repo'
} eq
'all'
) {
my
%options
=
%o
;
for
my
$repo
(
keys
%{
$self
->config->{
'repo'
} } ) {
$options
{
'repo'
} =
$repo
;
$self
->_clean(
%options
);
}
}
else
{
$self
->_clean(
%o
);
}
}
sub
_clean {
my
(
$self
,
%o
) =
@_
;
my
$options
= {
repo
=>
$o
{
'repo'
},
arches
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'arch'
},
backend
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
} ),
force
=>
$o
{
'force'
},
};
my
$plugin
=
$self
->_get_plugin(
type
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
options
=>
$options
,
);
$plugin
->clean();
}
sub
init {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
repo
=> {
type
=> SCALAR, },
arch
=> {
type
=> SCALAR,
optional
=> 1 },
}
);
my
$options
= {
repo
=>
$o
{
'repo'
},
arches
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'arch'
},
backend
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
} ),
};
my
$plugin
=
$self
->_get_plugin(
type
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
options
=>
$options
,
);
$plugin
->init(
$o
{
'arch'
} );
}
sub
list {
my
$self
=
shift
;
print
"Repository list:\n"
;
print
sprintf
"|%8s|%8s|%50s|\n"
,
'Type'
,
'Mirrored'
,
'Name'
;
for
my
$repo
(
sort
keys
%{
$self
->config->{repo} } ) {
my
$type
=
$self
->config->{repo}->{
$repo
}->{type};
my
$mirrored
=
$self
->config->{repo}->{
$repo
}->{url} ?
'Yes'
:
'No'
;
print
sprintf
"|%8s|%8s|%50s|\n"
,
$type
,
$mirrored
,
$repo
;
}
}
sub
mirror {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
'repo'
=> {
type
=> SCALAR },
'force'
=> {
type
=> BOOLEAN,
default
=> 0 },
'arch'
=> {
type
=> SCALAR,
optional
=> 1 },
'checksums'
=> {
type
=> SCALAR,
optional
=> 1 },
}
);
if
(
$o
{
'repo'
} eq
'all'
) {
my
%options
=
%o
;
for
my
$repo
(
keys
%{
$self
->config->{
'repo'
} } ) {
$options
{
'repo'
} =
$repo
;
$self
->_mirror(
%options
);
}
}
else
{
$self
->_mirror(
%o
);
}
}
sub
_mirror {
my
(
$self
,
%o
) =
@_
;
my
$options
= {
repo
=>
$o
{
'repo'
},
arches
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'arch'
},
url
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'url'
},
checksums
=>
$o
{
'checksums'
},
backend
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
} ),
ssl_ca
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'ca'
} ||
undef
,
ssl_cert
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'cert'
} ||
undef
,
ssl_key
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'key'
} ||
undef
,
force
=>
$o
{
'force'
},
};
my
$plugin
=
$self
->_get_plugin(
type
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
options
=>
$options
);
$plugin
->mirror();
}
sub
tag {
my
$self
=
shift
;
my
%o
= validate(
@_
,
{
'repo'
=> {
type
=> SCALAR },
'tag'
=> {
type
=> SCALAR },
'src-tag'
=> {
type
=> SCALAR,
default
=>
'head'
},
'symlink'
=> {
type
=> BOOLEAN,
default
=> 0 },
'force'
=> {
type
=> BOOLEAN,
default
=> 0 },
},
);
my
$options
= {
repo
=>
$o
{
'repo'
},
arches
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'arch'
},
backend
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
} ),
force
=>
$o
{
'force'
},
};
my
$plugin
=
$self
->_get_plugin(
type
=>
$self
->config->{
'repo'
}->{
$o
{
'repo'
} }->{
'type'
},
options
=>
$options
,
);
$plugin
->tag(
src_dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
},
tag
=>
$o
{
'src-tag'
} ),
src_tag
=>
$o
{
'src-tag'
},
dest_dir
=>
$self
->_get_repo_dir(
repo
=>
$o
{
'repo'
},
tag
=>
$o
{
'tag'
} ),
dest_tag
=>
$o
{
'tag'
},
symlink
=>
$o
{
'symlink'
},
hard_tag_regex
=>
$self
->config->{
'repo'
}->{
'hard_tag_regex'
}
||
$self
->config->{
'hard_tag_regex'
},
);
}
1;