* added 'force_project_delete'.
* added the pre-revprop-change hook and the post-revprop-change hook.
This commit is contained in:
parent
b4fdd8f888
commit
c02b59a9ca
@ -169,7 +169,7 @@ top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
wwwdir = @wwwdir@
|
||||
cfg_DATA = codepot.ini codepot.sql codepot.a2ldap
|
||||
cfg_SCRIPTS = start-commit pre-commit post-commit
|
||||
cfg_SCRIPTS = start-commit pre-commit post-commit pre-revprop-change post-revprop-change
|
||||
EXTRA_DIST = $(cfg_DATA) $(cfg_SCRIPTS)
|
||||
all: all-am
|
||||
|
||||
|
@ -136,6 +136,14 @@ file_dir = "@DEPOTDIR@/files"
|
||||
;------------------------------------------------------------------------------
|
||||
log_threshold = 0
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; When yes, a project member can delete a non-empty project containing
|
||||
; wiki pages, file uploads, etc. An empty project can be deleted any time
|
||||
; regardless of this option. A system administrator(sysadmin_userids) is
|
||||
; allowed to delete a non-empty project also regardless of this option.
|
||||
;------------------------------------------------------------------------------
|
||||
force_project_delete = "no"
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; customized footer
|
||||
;------------------------------------------------------------------------------
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
REPOBASE="`basename "${1}"`"
|
||||
REV="${2}"
|
||||
REVISION="${2}"
|
||||
USER="${3}"
|
||||
PROPNAME="${4}"
|
||||
ACTION="${5}"
|
||||
@ -9,5 +9,5 @@ ACTION="${5}"
|
||||
# [STDIN] PROPVAL ** the old property value is passed via STDIN.
|
||||
|
||||
# does not care if logging has failed.
|
||||
wget -q -O- "%API%/logRevpropChange/svn/${REPOBASE}/${REV}" 2>/dev/null
|
||||
wget -q -O- "%API%/logCodeRevpropChange/svn/${REPOBASE}/${REVISION}/${USER}/${PROPNAME}/${ACTION}" 2>/dev/null
|
||||
exit 0
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
REPOBASE="`basename "${1}"`"
|
||||
USER="${2}"
|
||||
REVISION="${2}"
|
||||
USER="${3}"
|
||||
PROPNAME="${4}"
|
||||
ACTION="${5}"
|
||||
|
@ -54,15 +54,14 @@ class API extends Controller
|
||||
*/
|
||||
}
|
||||
|
||||
function logCodeRevpropChange ($type, $repo, $rev, $propname)
|
||||
function logCodeRevpropChange ($type, $repo, $rev, $userid, $propname, $action)
|
||||
{
|
||||
$this->check_access ();
|
||||
|
||||
if (!isset($repo) || !isset($rev) || !isset($propname)) return;
|
||||
if (!isset($repo) || !isset($rev) || !isset($propname) || !isset($action)) return;
|
||||
|
||||
$this->load->model ('LogModel', 'logs');
|
||||
// TODO:
|
||||
//$this->logs->writeCodeRevpropChange ($type, $repo, $rev, '');
|
||||
$this->logs->writeCodeRevpropChange ($type, $repo, $rev, $userid, $propname, $action);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,10 +304,13 @@ class Project extends Controller
|
||||
{
|
||||
if ($data['project_confirm'] == 'yes')
|
||||
{
|
||||
$result = $this->projects->delete ($login['id'], $project);
|
||||
$result = $this->projects->delete (
|
||||
$login['id'], $project,
|
||||
($login['sysadmin?'] || CODEPOT_FORCE_PROJECT_DELETE));
|
||||
if ($result === FALSE)
|
||||
{
|
||||
$data['message'] = 'DATABASE ERROR';
|
||||
$data['project'] = $project;
|
||||
$this->load->view ($this->VIEW_DELETE, $data);
|
||||
}
|
||||
else
|
||||
|
@ -429,7 +429,7 @@ class Site extends Controller
|
||||
$this->load->view ($this->VIEW_LOG, $data);
|
||||
}
|
||||
|
||||
function wiki ($xlink)
|
||||
function wiki ($xlink = '')
|
||||
{
|
||||
$login = $this->login->getUser ();
|
||||
if (CODEPOT_SIGNIN_COMPULSORY && $login['id'] == '')
|
||||
|
@ -84,6 +84,7 @@ $lang['MSG_LOG_CHANGE_BY'] = 'Changed by %s';
|
||||
$lang['MSG_LOG_CREATE_BY'] = 'Created by %s';
|
||||
$lang['MSG_LOG_DELETE_BY'] = 'Deleted by %s';
|
||||
$lang['MSG_LOG_UPDATE_BY'] = 'Updated by %s';
|
||||
$lang['MSG_LOG_REVPROP_CHANGE_BY'] = 'Revision property %s changed by %s';
|
||||
|
||||
$lang['MSG_NO_DIFF'] = 'No difference found';
|
||||
$lang['MSG_NO_CODE_AVAIL'] = 'No source code available';
|
||||
|
@ -78,11 +78,13 @@ $lang['Username'] = '사용자명';
|
||||
$lang['Wiki'] = '위키';
|
||||
$lang['Wikis'] = '위키';
|
||||
|
||||
$lang['MSG_LOG_COMMIT_BY'] = '%s에 의해 커밋되었습니다';
|
||||
$lang['MSG_LOG_CHANGE_BY'] = '%s에 의해 변경되었습니다';
|
||||
$lang['MSG_LOG_CREATE_BY'] = '%s에 의해 생성되었습니다';
|
||||
$lang['MSG_LOG_DELETE_BY'] = '%s에 의해 삭제되었습니다';
|
||||
$lang['MSG_LOG_UPDATE_BY'] = '%s에 의해 갱신되었습니다';
|
||||
$lang['MSG_LOG_COMMIT_BY'] = '%s이(가) 커밋했습니다';
|
||||
$lang['MSG_LOG_CHANGE_BY'] = '%s이(가) 변경했습니다';
|
||||
$lang['MSG_LOG_CREATE_BY'] = '%s이(가) 생성했습니다';
|
||||
$lang['MSG_LOG_DELETE_BY'] = '%s이(가) 삭제했습니다';
|
||||
$lang['MSG_LOG_UPDATE_BY'] = '%s이(가) 갱신했습니다';
|
||||
$lang['MSG_LOG_REVPROP_CHANGE_BY'] = '리비전 속성 %s을(를) %s이(가) 변경했습니다';
|
||||
|
||||
|
||||
$lang['MSG_NO_DIFF'] = '차이점이 없습니다';
|
||||
$lang['MSG_NO_CODE_AVAIL'] = '소스코드가 없습니다';
|
||||
|
@ -53,6 +53,12 @@ class IssueModel extends Model
|
||||
if ($search->summary != '') $this->db->like ('summary', $search->summary);
|
||||
$this->db->select ('count(id) as count');
|
||||
$query = $this->db->get ('issue');
|
||||
if ($this->db->trans_status() === FALSE)
|
||||
{
|
||||
$this->db->trans_complete ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$result = $query->result();
|
||||
|
||||
$num = empty($result)? 0: $result[0]->count;
|
||||
|
@ -23,6 +23,12 @@ class LogModel extends Model
|
||||
|
||||
$this->db->select ('count(id) as count');
|
||||
$query = $this->db->get ('log');
|
||||
if ($this->db->trans_status() === FALSE)
|
||||
{
|
||||
$this->db->trans_complete ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$result = $query->result();
|
||||
|
||||
$num = empty($result)? 0: $result[0]->count;
|
||||
@ -66,25 +72,44 @@ class LogModel extends Model
|
||||
|
||||
if ($row->type == 'code')
|
||||
{
|
||||
list($type,$repo,$rev) = split('[,]', $row->message);
|
||||
$tmp['type'] = $type;
|
||||
$tmp['repo'] = $repo;
|
||||
$tmp['rev'] = $rev;
|
||||
|
||||
$log = @svn_log (
|
||||
'file:///'.CODEPOT_SVNREPO_DIR."/{$repo}",
|
||||
$rev, $rev, 1,SVN_DISCOVER_CHANGED_PATHS);
|
||||
if ($log === FALSE || count($log) < 1)
|
||||
if ($row->action == 'commit')
|
||||
{
|
||||
$tmp['time'] = '';
|
||||
$tmp['author'] = '';
|
||||
$tmp['message'] = '';
|
||||
list($type,$repo,$rev) = split('[,]', $row->message);
|
||||
|
||||
$tmp['type'] = $type;
|
||||
$tmp['repo'] = $repo;
|
||||
$tmp['rev'] = $rev;
|
||||
|
||||
$log = @svn_log (
|
||||
'file:///'.CODEPOT_SVNREPO_DIR."/{$repo}",
|
||||
$rev, $rev, 1,SVN_DISCOVER_CHANGED_PATHS);
|
||||
if ($log === FALSE || count($log) < 1)
|
||||
{
|
||||
$tmp['time'] = '';
|
||||
$tmp['author'] = '';
|
||||
$tmp['message'] = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmp['time'] = $log[0]['date'];
|
||||
$tmp['author'] = $log[0]['author'];
|
||||
$tmp['message'] = $log[0]['msg'];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmp['time'] = $log[0]['date'];
|
||||
$tmp['author'] = $log[0]['author'];
|
||||
$tmp['message'] = $log[0]['msg'];
|
||||
list($type,$repo,$rev,$propname,$action) = split('[,]', $row->message);
|
||||
|
||||
$tmp['type'] = $type;
|
||||
$tmp['repo'] = $repo;
|
||||
$tmp['rev'] = $rev;
|
||||
|
||||
$tmp['propname'] = $propname;
|
||||
$tmp['action'] = $action;
|
||||
|
||||
$tmp['time'] = $row->createdon;
|
||||
$tmp['author'] = $row->userid;
|
||||
}
|
||||
|
||||
$commits[$count]['message'] = $tmp;
|
||||
@ -110,6 +135,16 @@ class LogModel extends Model
|
||||
$this->write ($log);
|
||||
}
|
||||
|
||||
function writeCodeRevpropChange ($type, $repo, $rev, $userid, $propname, $action)
|
||||
{
|
||||
$log->type = 'code';
|
||||
$log->action = 'revpropchange';
|
||||
$log->projectid = $repo;
|
||||
$log->userid = $userid;
|
||||
$log->message = "{$type},{$repo},{$rev},{$propname},{$action}";
|
||||
$this->write ($log);
|
||||
}
|
||||
|
||||
function write ($log)
|
||||
{
|
||||
$this->db->trans_begin ();
|
||||
@ -119,6 +154,7 @@ class LogModel extends Model
|
||||
$this->db->set ('projectid', $log->projectid);
|
||||
$this->db->set ('message', $log->message);
|
||||
$this->db->set ('createdon', date('Y-m-d H:i:s'));
|
||||
$this->db->set ('userid', $log->userid);
|
||||
$this->db->insert ('log');
|
||||
|
||||
if ($this->db->trans_status() === FALSE)
|
||||
|
@ -57,7 +57,14 @@ class ProjectModel extends Model
|
||||
if ($search->id != '') $this->db->like ('id', $search->id);
|
||||
if ($search->name != '') $this->db->like ('name', $search->name);
|
||||
if ($search->summary != '') $this->db->like ('summary', $search->summary);
|
||||
|
||||
$query = $this->db->get ('project');
|
||||
if ($this->db->trans_status() === FALSE)
|
||||
{
|
||||
$this->db->trans_complete ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$result = $query->result();
|
||||
|
||||
$num = empty($result)? 0: $result[0]->count;
|
||||
@ -146,55 +153,43 @@ class ProjectModel extends Model
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// copy hook scripts to the top repository directory
|
||||
// overwriting existing scripts are ok as they are
|
||||
// just updated to the latest scripts anyway.
|
||||
$contents = @file_get_contents("{$cfgdir}/start-commit");
|
||||
if ($contents === FALSE)
|
||||
{
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
$hooks = array (
|
||||
"start-commit",
|
||||
"post-commit",
|
||||
"pre-revprop-change",
|
||||
"post-revprop-change"
|
||||
);
|
||||
|
||||
if (@file_put_contents (
|
||||
"{$repodir}/start-commit",
|
||||
str_replace('%API%', $api, $contents)) === FALSE)
|
||||
foreach ($hooks as $hook)
|
||||
{
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
// copy hook scripts to the top repository directory
|
||||
// overwriting existing scripts are ok as they are
|
||||
// just updated to the latest scripts anyway.
|
||||
$contents = @file_get_contents("{$cfgdir}/${hook}");
|
||||
if ($contents === FALSE)
|
||||
{
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$contents = @file_get_contents("{$cfgdir}/post-commit");
|
||||
if ($contents === FALSE)
|
||||
{
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
if (@file_put_contents (
|
||||
"{$repodir}/${hook}",
|
||||
str_replace('%API%', $api, $contents)) === FALSE)
|
||||
{
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (@file_put_contents(
|
||||
"{$repodir}/post-commit",
|
||||
str_replace('%API%', $api, $contents)) === FALSE)
|
||||
{
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// install hook scripts to the new project repository
|
||||
if (@chmod ("{$repodir}/start-commit", 0755) === FALSE ||
|
||||
@chmod ("{$repodir}/post-commit", 0755) === FALSE ||
|
||||
@symlink ("../../start-commit", "{$repodir}/{$project->id}/hooks/start-commit") === FALSE ||
|
||||
@symlink ("../../post-commit", "{$repodir}/{$project->id}/hooks/post-commit") === FALSE)
|
||||
{
|
||||
// keep {$repodir}/start-commit, {$repodir}/post-commit
|
||||
// to minimize impact on other projects. just delete the attempted
|
||||
// project repository directory.
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
// install the hook script to the new project repository
|
||||
if (@chmod ("{$repodir}/{$hook}", 0755) === FALSE ||
|
||||
@symlink ("../../{$hook}", "{$repodir}/{$project->id}/hooks/${hook}") === FALSE)
|
||||
{
|
||||
$this->deleteDirectory ("{$repodir}/{$project->id}");
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
$this->db->trans_commit ();
|
||||
@ -257,11 +252,36 @@ class ProjectModel extends Model
|
||||
}
|
||||
}
|
||||
|
||||
function delete ($userid, $project)
|
||||
function delete ($userid, $project, $force = FALSE)
|
||||
{
|
||||
// TODO: check if userid can do this..
|
||||
$this->db->trans_begin ();
|
||||
|
||||
if ($force)
|
||||
{
|
||||
$this->db->where ('projectid', $project->id);
|
||||
$this->db->delete ('wiki');
|
||||
|
||||
$this->db->where ('projectid', $project->id);
|
||||
$this->db->delete ('issue_change');
|
||||
|
||||
$this->db->where ('projectid', $project->id);
|
||||
$this->db->delete ('issue');
|
||||
|
||||
$this->db->where ('projectid', $project->id);
|
||||
$query = $this->db->get ('file');
|
||||
if ($this->db->trans_status() === FALSE)
|
||||
{
|
||||
$this->db->trans_rollback ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$result = $query->result ();
|
||||
|
||||
$this->db->where ('projectid', $project->id);
|
||||
$this->db->delete ('file');
|
||||
}
|
||||
|
||||
$this->db->where ('id', $project->id);
|
||||
$this->db->delete ('project');
|
||||
|
||||
@ -288,6 +308,13 @@ class ProjectModel extends Model
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($force && count($result) > 0)
|
||||
{
|
||||
// no way to roll back file delete.
|
||||
// so deletion is done here.
|
||||
$this->_delete_files_uploaded ($result);
|
||||
}
|
||||
|
||||
$this->db->trans_commit ();
|
||||
return TRUE;
|
||||
}
|
||||
@ -394,6 +421,13 @@ class ProjectModel extends Model
|
||||
if ($this->db->trans_status() === FALSE) return FALSE;
|
||||
return ($count == 1)? TRUE: FALSE;
|
||||
}
|
||||
|
||||
|
||||
function _delete_files_uploaded ($files)
|
||||
{
|
||||
foreach ($files as $file)
|
||||
@unlink (CODEPOT_FILE_DIR . "/{$file->encname}");
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -200,14 +200,26 @@ $this->load->view (
|
||||
|
||||
print '<td class="details">';
|
||||
print '<span class="description">';
|
||||
$fmt = $this->lang->line (
|
||||
'MSG_LOG_'.strtoupper($log['action']).'_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $code['author']));
|
||||
if ($log['action'] == 'revpropchange')
|
||||
{
|
||||
$fmt = $this->lang->line ('MSG_LOG_REVPROP_CHANGE_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $code['propname'], $code['author']));
|
||||
//$code['action']
|
||||
}
|
||||
else
|
||||
{
|
||||
$fmt = $this->lang->line (
|
||||
'MSG_LOG_'.strtoupper($log['action']).'_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $code['author']));
|
||||
}
|
||||
print '</span>';
|
||||
|
||||
print '<pre class="message">';
|
||||
print htmlspecialchars ($code['message']);
|
||||
print '</pre>';
|
||||
if ($log['action'] != 'revpropchange')
|
||||
{
|
||||
print '<pre class="message">';
|
||||
print htmlspecialchars ($code['message']);
|
||||
print '</pre>';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -118,15 +118,26 @@ $this->load->view (
|
||||
print '<td></td>';
|
||||
print '<td colspan=1 class="details">';
|
||||
print '<span class="description">';
|
||||
$fmt = $this->lang->line (
|
||||
'MSG_LOG_'.strtoupper($log['action']).'_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $x['author']));
|
||||
if ($log['action'] == 'revpropchange')
|
||||
{
|
||||
$fmt = $this->lang->line ('MSG_LOG_REVPROP_CHANGE_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $x['propname'], $x['author']));
|
||||
}
|
||||
else
|
||||
{
|
||||
$fmt = $this->lang->line (
|
||||
'MSG_LOG_'.strtoupper($log['action']).'_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $x['author']));
|
||||
}
|
||||
print '</span>';
|
||||
|
||||
print '<pre class="message">';
|
||||
$sm = strtok (trim ($x['message']), "\r\n");
|
||||
print htmlspecialchars ($sm);
|
||||
print '</pre>';
|
||||
if ($log['action'] != 'revpropchange')
|
||||
{
|
||||
print '<pre class="message">';
|
||||
$sm = strtok (trim ($x['message']), "\r\n");
|
||||
print htmlspecialchars ($sm);
|
||||
print '</pre>';
|
||||
}
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
|
@ -116,15 +116,27 @@ foreach ($latest_projects as $project)
|
||||
print '<td></td>';
|
||||
print '<td colspan=2 class="details">';
|
||||
print '<span class="description">';
|
||||
$fmt = $this->lang->line (
|
||||
'MSG_LOG_'.strtoupper($log['action']).'_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $x['author']));
|
||||
|
||||
if ($log['action'] == 'revpropchange')
|
||||
{
|
||||
$fmt = $this->lang->line ('MSG_LOG_REVPROP_CHANGE_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $x['propname'], $x['author']));
|
||||
}
|
||||
else
|
||||
{
|
||||
$fmt = $this->lang->line (
|
||||
'MSG_LOG_'.strtoupper($log['action']).'_BY');
|
||||
print htmlspecialchars (sprintf($fmt, $x['author']));
|
||||
}
|
||||
print '</span>';
|
||||
|
||||
print '<pre class="message">';
|
||||
$sm = strtok (trim ($x['message']), "\r\n");
|
||||
print htmlspecialchars ($sm);
|
||||
print '</pre>';
|
||||
if ($log['action'] != 'revpropchange')
|
||||
{
|
||||
print '<pre class="message">';
|
||||
$sm = strtok (trim ($x['message']), "\r\n");
|
||||
print htmlspecialchars ($sm);
|
||||
print '</pre>';
|
||||
}
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ function load_ini ($file)
|
||||
|
||||
array ('log_threshold', 'integer', 0),
|
||||
|
||||
array ('force_project_delete', 'boolean', FALSE),
|
||||
array ('footer', 'string', '')
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user