<?php
class
IDF_Plugin_SyncMercurial
{
static
public
function
entry(
$signal
, &
$params
)
{
if
(!Pluf::f(
'idf_plugin_syncmercurial_passwd_file'
, false)
or
!Pluf::f(
'idf_plugin_syncmercurial_path'
, false)
or
!Pluf::f(
'idf_plugin_syncmercurial_hgrc'
, false)) {
return
;
}
include_once
'File/Passwd/Authdigest.php'
;
$plug
=
new
IDF_Plugin_SyncMercurial();
switch
(
$signal
) {
case
'IDF_Project::created'
:
$plug
->processMercurialCreate(
$params
[
'project'
]);
break
;
case
'IDF_Project::membershipsUpdated'
:
$plug
->processSyncAuthz(
$params
[
'project'
]);
break
;
case
'Pluf_User::passwordUpdated'
:
$plug
->processSyncPasswd(
$params
[
'user'
]);
break
;
case
'hgchangegroup.php::run'
:
$plug
->processSyncTimeline(
$params
);
break
;
}
}
function
processMercurialCreate(
$project
)
{
if
(
$project
->getConf()->getVal(
'scm'
) !=
'mercurial'
) {
return
false;
}
$shortname
=
$project
->shortname;
if
(false===(
$mercurial_path
=Pluf::f(
'idf_plugin_syncmercurial_path'
,false))) {
throw
new
Pluf_Exception_SettingError(
"'idf_plugin_syncmercurial_path' must be defined in your configuration file."
);
}
if
(
file_exists
(
$mercurial_path
.
'/'
.
$shortname
)) {
throw
new
Exception(sprintf(__(
'The repository %s already exists.'
),
$mercurial_path
.
'/'
.
$shortname
));
}
$return
= 0;
$output
=
array
();
$cmd
= sprintf(Pluf::f(
'hg_path'
,
'hg'
).
' init %s'
,
escapeshellarg
(
$mercurial_path
.
'/'
.
$shortname
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$ll
=
exec
(
$cmd
,
$output
,
$return
);
return
(
$return
== 0);
}
function
processSyncPasswd(
$user
)
{
$passwd_file
= Pluf::f(
'idf_plugin_syncmercurial_passwd_file'
);
if
(!
file_exists
(
$passwd_file
)
or
!
is_writable
(
$passwd_file
)) {
return
false;
}
$ht
=
new
File_Passwd_Authbasic(
$passwd_file
);
$ht
->load();
$ht
->setMode(Pluf::f(
'idf_plugin_syncmercurial_passwd_mode'
,
FILE_PASSWD_SHA));
if
(
$ht
->userExists(
$user
->login)) {
$ht
->changePasswd(
$user
->login,
$this
->getMercurialPass(
$user
));
}
else
{
$ht
->addUser(
$user
->login,
$this
->getMercurialPass(
$user
));
}
$ht
->save();
return
true;
}
function
processSyncAuthz(
$project
)
{
if
(
$project
->getConf()->getVal(
'scm'
) !=
'mercurial'
) {
return
false;
}
$this
->SyncAccess(
$project
);
$this
->generateProjectPasswd(
$project
);
}
function
getMercurialPass(
$user
){
return
substr
(sha1(
$user
->password.Pluf::f(
'secret_key'
)), 0, 8);
}
function
generateProjectPasswd(
$project
)
{
$passwd_file
= Pluf::f(
'idf_plugin_syncmercurial_passwd_file'
);
if
(!
file_exists
(
$passwd_file
)
or
!
is_writable
(
$passwd_file
)) {
throw
new
Exception (sprintf(__(
'%s does not exist or is not writable.'
),
$passwd_file
));
}
$ht
=
new
File_Passwd_Authbasic(
$passwd_file
);
$ht
->setMode(Pluf::f(
'idf_plugin_syncmercurial_passwd_mode'
,
FILE_PASSWD_SHA));
$ht
->load();
$mem
=
$project
->getMembershipData();
$members
=
array_merge
((
array
)
$mem
[
'members'
], (
array
)
$mem
[
'owners'
],
(
array
)
$mem
[
'authorized'
]);
foreach
(
$members
as
$user
) {
if
(
$ht
->userExists(
$user
->login)) {
$ht
->changePasswd(
$user
->login,
$this
->getMercurialPass(
$user
));
}
else
{
$ht
->addUser(
$user
->login,
$this
->getMercurialPass(
$user
));
}
}
$ht
->save();
}
function
SyncAccess(
$project
)
{
$shortname
=
$project
->shortname;
$hgrc_file
= Pluf::f(
'idf_plugin_syncmercurial_path'
).sprintf(
'/%s/.hg/hgrc'
,
$shortname
);
$allow_push
=
''
;
$mem
=
$project
->getMembershipData();
foreach
(
$mem
[
'owners'
]
as
$v
) {
$allow_push
.=
$v
->login.
' '
;
}
foreach
(
$mem
[
'members'
]
as
$v
) {
$allow_push
.=
$v
->login.
' '
;
}
if
(
is_file
(
$hgrc_file
)) {
$tmp_content
=
parse_ini_file
(
$hgrc_file
, true);
$tmp_content
[
'web'
][
'allow_push'
] =
$allow_push
;
}
else
{
$tmp_content
= Pluf::f(
'idf_plugin_syncmercurial_hgrc'
);
$tmp_content
[
'web'
][
'allow_push'
] =
$allow_push
;
}
$fcontent
=
''
;
foreach
(
$tmp_content
as
$key
=>
$elem
){
$fcontent
.=
'['
.
$key
.
"]\n"
;
foreach
(
$elem
as
$key2
=>
$elem2
){
$fcontent
.=
$key2
.
' = '
.
$elem2
.
"\n"
;
}
}
file_put_contents
(
$hgrc_file
,
$fcontent
, LOCK_EX);
$private_file
= Pluf::f(
'idf_plugin_syncmercurial_private_include'
);
$notify_file
= Pluf::f(
'idf_plugin_syncmercurial_private_notify'
);
$fcontent
=
''
;
foreach
(Pluf::factory(
'IDF_Project'
)->getList()
as
$project
) {
$conf
=
new
IDF_Conf();
$conf
->setProject(
$project
);
if
(
$project
->
private
== true){
$mem
=
$project
->getMembershipData();
$user
=
''
;
foreach
(
$mem
[
'owners'
]
as
$v
) {
$user
.=
$v
->login.
' '
;
}
foreach
(
$mem
[
'members'
]
as
$v
) {
$user
.=
$v
->login.
' '
;
}
foreach
(
$mem
[
'authorized'
]
as
$v
) {
$user
.=
$v
->login.
' '
;
}
$fcontent
.=
'<Location '
. sprintf(Pluf::f(
'idf_plugin_syncmercurial_private_url'
),
$project
->shortname).
'>'
.
"\n"
;
$fcontent
.=
'AuthType Basic'
.
"\n"
;
$fcontent
.=
'AuthName "Restricted"'
.
"\n"
;
$fcontent
.= sprintf(
'AuthUserFile %s'
, Pluf::f(
'idf_plugin_syncmercurial_passwd_file'
)).
"\n"
;
$fcontent
.= sprintf(
'Require user %s'
,
$user
).
"\n"
;
$fcontent
.=
'</Location>'
.
"\n\n"
;
}
}
file_put_contents
(
$private_file
,
$fcontent
, LOCK_EX);
file_put_contents
(
$notify_file
,
' '
, LOCK_EX);
return
true;
}
public
function
processSyncTimeline(
$params
)
{
$pname
=
basename
(
$params
[
'rel_dir'
]);
try
{
$project
= IDF_Project::getOr404(
$pname
);
}
catch
(Pluf_HTTP_Error404
$e
) {
Pluf_Log::event(
array
(
'IDF_Plugin_SyncMercurial::processSyncTimeline'
,
'Project not found.'
,
array
(
$pname
,
$params
)));
return
false;
}
Pluf_Log::debug(
array
(
'IDF_Plugin_SyncMercurial::processSyncTimeline'
,
'Project found'
,
$pname
,
$project
->id));
IDF_Scm::syncTimeline(
$project
, true);
Pluf_Log::event(
array
(
'IDF_Plugin_SyncMercurial::processSyncTimeline'
,
'sync'
,
array
(
$pname
,
$project
->id)));
}
}