<?php
class
IDF_Scm_Svn
extends
IDF_Scm
{
public
$username
=
''
;
public
$password
=
''
;
private
$assoc
=
array
(
'dir'
=>
'tree'
,
'file'
=>
'blob'
);
public
function
__construct(
$repo
,
$project
=null)
{
$this
->repo =
$repo
;
$this
->project =
$project
;
$this
->cache[
'commitmess'
] =
array
();
}
public
function
isAvailable()
{
return
true;
}
public
function
getRepositorySize()
{
if
(
strpos
(
$this
->repo,
'file://'
) !== 0) {
return
-1;
}
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
'du -skD '
.
escapeshellarg
(
substr
(
$this
->repo, 7));
$out
=
explode
(
' '
, shell_exec(
$cmd
), 2);
return
(int)
$out
[0]*1024;
}
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
getAuthAccessUrl(
$project
,
$user
)
{
$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
)) {
$scm
=
new
IDF_Scm_Svn(
$rep
,
$project
);
$scm
->username =
$conf
->getVal(
'svn_username'
);
$scm
->password =
$conf
->getVal(
'svn_password'
);
return
$scm
;
}
else
{
$rep
= sprintf(Pluf::f(
'svn_repositories'
),
$project
->shortname);
return
new
IDF_Scm_Svn(
$rep
,
$project
);
}
}
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
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
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.
'/'
.self::smartEncode(
$path
)),
escapeshellarg
(
$rev
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$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(
$commit
,
$folder
=
'/'
,
$branch
=null)
{
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' ls --xml --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.self::smartEncode(
$folder
)),
escapeshellarg
(
$commit
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$xml
= simplexml_load_string(shell_exec(
$cmd
));
$res
=
array
();
$folder
= (
strlen
(
$folder
)
and
(
$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
[
'efullpath'
] = self::smartEncode(
$file
[
'fullpath'
]);
$file
[
'date'
] =
gmdate
(
'Y-m-d H:i:s'
,
strtotime
((string)
$entry
->commit->
date
));
$file
[
'rev'
] = (string)
$entry
->commit[
'revision'
];
$file
[
'log'
] =
$this
->getCommitMessage(
$file
[
'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(
$rev
=
'HEAD'
)
{
if
(isset(
$this
->cache[
'commitmess'
][
$rev
])) {
return
$this
->cache[
'commitmess'
][
$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
(
$this
->repo),
escapeshellarg
(
$rev
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$xml
= simplexml_load_string(shell_exec(
$cmd
));
$this
->cache[
'commitmess'
][
$rev
] = (string)
$xml
->logentry->msg;
return
$this
->cache[
'commitmess'
][
$rev
];
}
public
function
getPathInfo(
$filename
,
$rev
=null)
{
if
(
$rev
== null) {
$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.
'/'
.self::smartEncode(
$filename
)),
escapeshellarg
(
$rev
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$xml
= simplexml_load_string(shell_exec(
$cmd
));
if
(!isset(
$xml
->entry)) {
return
false;
}
$entry
=
$xml
->entry;
$file
=
array
();
$file
[
'fullpath'
] =
$filename
;
$file
[
'hash'
] = (string)
$entry
->repository->uuid;
$file
[
'type'
] =
$this
->assoc[(string)
$entry
[
'kind'
]];
$pathinfo
=
pathinfo
(
$filename
);
$file
[
'file'
] =
$pathinfo
[
'basename'
];
$file
[
'rev'
] =
$rev
;
$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_only
=false)
{
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' cat --username=%s --password=%s %s@%s'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/'
.self::smartEncode(
$def
->fullpath)),
escapeshellarg
(
$def
->rev));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
return
(
$cmd_only
) ?
$cmd
: shell_exec(
$cmd
);
}
public
function
getBranches()
{
if
(isset(
$this
->cache[
'branches'
])) {
return
$this
->cache[
'branches'
];
}
$res
=
array
();
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' ls --username=%s --password=%s %s@HEAD'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/branches'
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
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'
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
exec
(
$cmd
,
$out
,
$ret
);
if
(
$ret
== 0) {
$res
=
array
(
'trunk'
=>
'trunk'
) +
$res
;
}
$this
->cache[
'branches'
] =
$res
;
return
$res
;
}
public
function
getTags()
{
if
(isset(
$this
->cache[
'tags'
])) {
return
$this
->cache[
'tags'
];
}
$res
=
array
();
$cmd
= sprintf(Pluf::f(
'svn_path'
,
'svn'
).
' ls --username=%s --password=%s %s@HEAD'
,
escapeshellarg
(
$this
->username),
escapeshellarg
(
$this
->password),
escapeshellarg
(
$this
->repo.
'/tags'
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
exec
(
$cmd
,
$out
,
$ret
);
if
(
$ret
== 0) {
foreach
(
$out
as
$entry
) {
if
(
substr
(trim(
$entry
), -1) ==
'/'
) {
$tag
=
substr
(trim(
$entry
), 0, -1);
$res
[
$tag
] =
'tags/'
.
$tag
;
}
}
}
ksort(
$res
);
$this
->cache[
'tags'
] =
$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
inTags(
$commit
,
$path
)
{
foreach
(
$this
->getTags()
as
$tag
=>
$tpath
) {
if
(
$tpath
and
0 ===
strpos
(
$path
,
$tpath
)) {
return
array
(
$tag
);
}
}
return
array
();
}
public
function
getCommit(
$commit
,
$getdiff
=false)
{
if
(!
$this
->isValidRevision(
$commit
)) {
return
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
(
$commit
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$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(
$commit
) :
''
;
$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
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$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));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
return
shell_exec(
$cmd
);
}
public
function
getChangeLog(
$branch
=null,
$n
=10)
{
if
(
$branch
!=
'HEAD'
and
!preg_match(
'/^\d+$/'
,
$branch
)) {
$branch
=
'HEAD'
;
}
$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
(
$branch
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$xmlRes
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlRes
);
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
));
$split
= preg_split(
"[\n\r]"
, (string)
$entry
->msg, 2);
$log
[
'title'
] =
$split
[0];
$log
[
'commit'
] = (string)
$entry
[
'revision'
];
$log
[
'full_message'
] = (isset(
$split
[1])) ? trim(
$split
[1]) :
''
;
$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.
'/'
.self::smartEncode(
$path
)),
escapeshellarg
(
$rev
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$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.
'/'
.self::smartEncode(
$path
)),
escapeshellarg
(
$rev
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$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
));
$cmd
= Pluf::f(
'idf_exec_cmd_prefix'
,
''
).
$cmd
;
$xmlInfo
= shell_exec(
$cmd
);
$xml
= simplexml_load_string(
$xmlInfo
);
return
(string)
$xml
->entry->commit[
'revision'
];
}
}