<?php
class
IDF_Scm_Svn
extends
IDF_Scm
{
public
$repo
=
''
;
public
$username
=
''
;
public
$password
=
''
;
private
$assoc
=
array
(
'dir'
=>
'tree'
,
'file'
=>
'blob'
);
private
$commit
=
array
();
public
function
__construct(
$repo
,
$username
=
''
,
$password
=
''
)
{
$this
->repo =
$repo
;
$this
->username =
$username
;
$this
->password =
$password
;
}
public
function
isAvailable()
{
return
true;
}
public
function
findAuthor(
$author
)
{
$sql
=
new
Pluf_SQL(
'login=%s'
,
array
(trim(
$author
)));
$users
= Pluf::factory(
'Pluf_User'
)->getList(
array
(
'filter'
=>
$sql
->gen()));
return
(
$users
->
count
() > 0) ?
$users
[0] : null;
}
public
static
function
getAnonymousAccessUrl(
$project
)
{
$conf
=
$project
->getConf();
if
(false !== (
$url
=
$conf
->getVal(
'svn_remote_url'
, false))
&& !
empty
(
$url
)) {
return
$url
;
}
return
sprintf(Pluf::f(
'svn_remote_url'
),
$project
->shortname);
}
public
static
function
factory(
$project
)
{
$conf
=
$project
->getConf();
if
(false !== (
$rep
=
$conf
->getVal(
'svn_remote_url'
, false))
&& !
empty
(
$rep
)) {
return
new
IDF_Scm_Svn(
$rep
,
$conf
->getVal(
'svn_username'
),
$conf
->getVal(
'svn_password'
));
}
else
{
$rep
= sprintf(Pluf::f(
'svn_repositories'
),
$project
->shortname);
return
new
IDF_Scm_Svn(
$rep
);
}
}
public
function
isValidRevision(
$rev
)
{
if
(
$rev
==
'HEAD'
) {
return
true;
}
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' info --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo),
escapeshellarg
(
$rev
));
exec
(
$cmd
,
$out
,
$ret
);
return
(0 ==
$ret
);
}
public
function
testHash(
$rev
,
$path
=
''
)
{
if
(
$rev
===
'HEAD'
&&
$path
===
''
) {
return
'commit'
;
}
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' info --xml --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.
$path
),
escapeshellarg
(
$rev
));
$xmlInfo
= shell_exec(
$cmd
);
try
{
$xml
= simplexml_load_string(
$xmlInfo
);
}
catch
(Exception
$e
) {
return
false;
}
if
(!isset(
$xml
->entry)) {
return
false;
}
return
'commit'
;
}
public
function
getTree(
$rev
=
'HEAD'
,
$folder
=
''
)
{
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' ls --xml --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.
$folder
),
escapeshellarg
(
$rev
));
$xmlLs
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlLs
);
$res
=
array
();
$folder
= (
strlen
(
$folder
)) ?
$folder
.
'/'
:
''
;
foreach
(
$xml
->list->entry
as
$entry
) {
$file
=
array
();
$file
[
'type'
] =
$this
->assoc[(string)
$entry
[
'kind'
]];
$file
[
'file'
] = (string)
$entry
->name;
$file
[
'fullpath'
] =
$folder
.((string)
$entry
->name);
$file
[
'date'
] =
gmdate
(
'Y-m-d H:i:s'
,
strtotime
((string)
$entry
->commit->
date
));
$file
[
'rev'
] = (string)
$entry
->commit[
'revision'
];
$currentReposFile
=
$this
->repo.
'/'
.
$folder
.
$file
[
'file'
];
$file
[
'log'
] =
$this
->getCommitMessage(
$currentReposFile
,
$rev
);
if
(
$file
[
'type'
] ==
'blob'
) {
$file
[
'size'
] = (string)
$entry
->size;
}
$file
[
'author'
] = (string)
$entry
->commit->author;
$file
[
'perm'
] =
''
;
$res
[] = (object)
$file
;
}
return
$res
;
}
private
function
getCommitMessage(
$file
,
$rev
=
'HEAD'
)
{
if
(isset(
$commit
[
$rev
]))
return
$commit
[
$rev
];
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' log --xml --limit 1 --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$file
),
escapeshellarg
(
$rev
));
$xmlLog
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlLog
);
$commit
[
$rev
]=(string)
$xml
->logentry->msg;
return
(string)
$xml
->logentry->msg;
}
public
function
getPathInfo(
$totest
,
$rev
=
'HEAD'
)
{
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' info --xml --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.
$totest
),
escapeshellarg
(
$rev
));
$xmlInfo
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlInfo
);
$entry
=
$xml
->entry;
$file
=
array
();
$file
[
'fullpath'
] =
$totest
;
$file
[
'hash'
] = (string)
$entry
->repository->uuid;
$file
[
'type'
] =
$this
->assoc[(string)
$entry
[
'kind'
]];
$file
[
'file'
] =
$totest
;
$file
[
'rev'
] = (string)
$entry
->commit[
'revision'
];
$file
[
'author'
] = (string)
$entry
->author;
$file
[
'date'
] =
gmdate
(
'Y-m-d H:i:s'
,
strtotime
((string)
$entry
->commit->
date
));
$file
[
'size'
] = (string)
$entry
->size;
$file
[
'log'
] =
''
;
return
(object)
$file
;
}
public
function
getFile(
$def
)
{
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' cat --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.
$def
->fullpath),
escapeshellarg
(
$def
->rev));
return
shell_exec(
$cmd
);
}
public
function
getBranches()
{
if
(isset(
$this
->cache[
'branches'
])) {
return
$this
->cache[
'branches'
];
}
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' ls --username=%s --password=%s %s@HEAD'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/branches'
));
exec
(
$cmd
,
$out
,
$ret
);
if
(
$ret
== 0) {
foreach
(
$out
as
$entry
) {
if
(
substr
(trim(
$entry
), -1) ==
'/'
) {
$branch
=
substr
(trim(
$entry
), 0, -1);
$res
[
$branch
] =
'branches/'
.
$branch
;
}
}
}
ksort(
$res
);
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' info --username=%s --password=%s %s@HEAD'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/trunk'
));
exec
(
$cmd
,
$out
,
$ret
);
if
(
$ret
== 0) {
$res
=
array_merge
(
array
(
'trunk'
=>
'trunk'
),
$res
);
}
$this
->cache[
'branches'
] =
$res
;
return
$res
;
}
public
function
getMainBranch()
{
return
'HEAD'
;
}
public
function
inBranches(
$commit
,
$path
)
{
foreach
(
$this
->getBranches()
as
$branch
=>
$bpath
) {
if
(
$bpath
and
0 ===
strpos
(
$path
,
$bpath
)) {
return
array
(
$branch
);
}
}
return
array
();
}
public
function
getCommit(
$rev
=
'HEAD'
,
$getdiff
=false)
{
$res
=
array
();
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' log --xml --limit 1 -v --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo),
escapeshellarg
(
$rev
));
$xmlRes
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlRes
);
$res
[
'author'
] = (string)
$xml
->logentry->author;
$res
[
'date'
] =
gmdate
(
'Y-m-d H:i:s'
,
strtotime
((string)
$xml
->logentry->
date
));
$res
[
'title'
] = (string)
$xml
->logentry->msg;
$res
[
'commit'
] = (string)
$xml
->logentry[
'revision'
];
$res
[
'changes'
] = (
$getdiff
) ?
$this
->getDiff(
$rev
) :
''
;
$res
[
'tree'
] =
''
;
return
(object)
$res
;
}
public
function
isCommitLarge(
$commit
=
'HEAD'
)
{
if
(
substr
(
$this
->repo, 0, 7) !=
'file://'
) {
return
false;
}
$repo
=
substr
(
$this
->repo, 7);
$cmd
= sprintf(Pluf::f(
'svnlook_path'
,
'svnlook'
).
' changed -r %s %s'
,
escapeshellarg
(
$commit
),
escapeshellarg
(
$repo
));
$out
= shell_exec(
$cmd
);
$lines
= preg_split(
"/\015\012|\015|\012/"
,
$out
);
return
(
count
(
$lines
) > 100);
}
private
function
getDiff(
$rev
=
'HEAD'
)
{
$res
=
array
();
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' diff -c %s --username=%s --password=%s %s'
,
escapeshellarg
(
$rev
),
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo));
return
shell_exec(
$cmd
);
}
public
function
getChangeLog(
$rev
=
'HEAD'
,
$n
=10)
{
$res
=
array
();
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' log --xml -v --limit %s --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$n
),
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo),
escapeshellarg
(
$rev
));
$xmlRes
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlRes
);
$res
=
array
();
foreach
(
$xml
->logentry
as
$entry
) {
$log
=
array
();
$log
[
'author'
] = (string)
$entry
->author;
$log
[
'date'
] =
gmdate
(
'Y-m-d H:i:s'
,
strtotime
((string)
$entry
->
date
));
$log
[
'title'
] = (string)
$entry
->msg;
$log
[
'commit'
] = (string)
$entry
[
'revision'
];
$log
[
'full_message'
] =
''
;
$res
[] = (object)
$log
;
}
return
$res
;
}
public
function
getProperties(
$rev
,
$path
=
''
)
{
$res
=
array
();
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' proplist --xml --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.
$path
),
escapeshellarg
(
$rev
));
$xmlProps
= shell_exec(
$cmd
);
$props
= simplexml_load_string(
$xmlProps
);
if
(!isset(
$props
->target)) {
return
$res
;
}
foreach
(
$props
->target->property
as
$prop
) {
$key
= (string)
$prop
[
'name'
];
$res
[
$key
] =
$this
->getProperty(
$key
,
$rev
,
$path
);
}
return
$res
;
}
private
function
getProperty(
$property
,
$rev
,
$path
=
''
)
{
$res
=
array
();
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' propget --xml %s --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$property
),
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.
$path
),
escapeshellarg
(
$rev
));
$xmlProp
= shell_exec(
$cmd
);
$prop
= simplexml_load_string(
$xmlProp
);
return
(string)
$prop
->target->property;
}
public
function
getLastCommit(
$rev
=
'HEAD'
)
{
$xmlInfo
=
''
;
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' info --xml --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo),
escapeshellarg
(
$rev
));
$xmlInfo
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlInfo
);
return
(string)
$xml
->entry->commit[
'revision'
];
}
}