supported directory download
This commit is contained in:
parent
c8eb4f1d0d
commit
73d47592aa
@ -223,7 +223,7 @@ class Code extends Controller
|
||||
{
|
||||
$this->load->model ('ProjectModel', 'projects');
|
||||
$this->load->model ('SubversionModel', 'subversion');
|
||||
|
||||
|
||||
$login = $this->login->getUser ();
|
||||
if (CODEPOT_SIGNIN_COMPULSORY && $login['id'] == '')
|
||||
redirect ("main/signin/" . $this->converter->AsciiTohex(current_url()));
|
||||
@ -665,7 +665,7 @@ class Code extends Controller
|
||||
if ($file === FALSE)
|
||||
{
|
||||
$data['project'] = $project;
|
||||
$data['message'] = 'Failed to get file';
|
||||
$data['message'] = "Failed to get a file - $path";
|
||||
$this->load->view ($this->VIEW_ERROR, $data);
|
||||
}
|
||||
else if ($file['type'] == 'file')
|
||||
@ -682,33 +682,49 @@ class Code extends Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$data['project'] = $project;
|
||||
$data['headpath'] = $path;
|
||||
$data['file'] = $file;
|
||||
$forced_name = $projectid . $file['fullpath'];
|
||||
$forced_name = str_replace ('/', '-', $forced_name);
|
||||
//$tag = $this->subversion->getRevProp (
|
||||
// $projectid, $file['created_rev'], CODEPOT_SVN_TAG_PROPERTY);
|
||||
//if ($tag === FALSE) $tag = '';
|
||||
//if (!empty($tag))
|
||||
//{
|
||||
// $forced_name = $forced_name . '-' . $tag;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
$forced_name = $forced_name . '-r' . $file['created_rev'];
|
||||
//}
|
||||
|
||||
$data['revision'] = $rev;
|
||||
$data['prev_revision'] =
|
||||
$this->subversion->getPrevRev ($projectid, $path, $rev);
|
||||
$data['next_revision'] =
|
||||
$this->subversion->getNextRev ($projectid, $path, $rev);
|
||||
|
||||
$data['readme_text'] = '';
|
||||
$data['readme_file'] = '';
|
||||
foreach (explode(',', CODEPOT_CODE_FOLDER_README) as $rf)
|
||||
$filename = $this->subversion->zipSubdir ($projectid, $path, $rev, $forced_name);
|
||||
if ($filename === FALSE)
|
||||
{
|
||||
$rf = trim($rf);
|
||||
if (strlen($rf) > 0)
|
||||
{
|
||||
$readme = $this->subversion->getFile ($projectid, $path . '/' . $rf, $rev);
|
||||
if ($readme !== FALSE)
|
||||
{
|
||||
$data['readme_text'] = $readme['content'];
|
||||
$data['readme_file'] = $rf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data['project'] = $project;
|
||||
$data['message'] = "Failed to zip a directory for $path";
|
||||
$this->load->view ($this->VIEW_ERROR, $data);
|
||||
}
|
||||
else
|
||||
{
|
||||
$dir_name = $filename . '.d';
|
||||
$zip_name = $filename . '.zip';
|
||||
|
||||
$forced_zip_name = $forced_name . '.zip';
|
||||
|
||||
header ('Content-Description: File Transfer');
|
||||
header ('Content-Type: application/zip');
|
||||
header ('Content-Disposition: attachment; filename='. $forced_zip_name);
|
||||
header ('Content-Transfer-Encoding: binary');
|
||||
header ('Content-Length: ' . filesize($zip_name));
|
||||
flush ();
|
||||
|
||||
@readfile ($zip_name);
|
||||
// meaningless to show the error page after headers
|
||||
// have been sent event if readfile fails.
|
||||
|
||||
codepot_delete_files ($dir_name, TRUE);
|
||||
@unlink ($zip_name);
|
||||
@unlink ($filename);
|
||||
}
|
||||
$this->load->view ($this->VIEW_FOLDER, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -737,7 +753,7 @@ class Code extends Controller
|
||||
if ($file === FALSE)
|
||||
{
|
||||
$data['project'] = $project;
|
||||
$data['message'] = "Failed to get file - %path";
|
||||
$data['message'] = "Failed to get file - $path";
|
||||
$this->load->view ($this->VIEW_ERROR, $data);
|
||||
}
|
||||
|
||||
@ -982,8 +998,7 @@ class Code extends Controller
|
||||
$stats[$date] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ksort ($stats);
|
||||
$stats_count = count($stats);
|
||||
$idx = 1;
|
||||
@ -994,24 +1009,23 @@ class Code extends Controller
|
||||
$min_year = substr($k, 0, 4);
|
||||
$min_month = substr($k, 5, 2);
|
||||
}
|
||||
|
||||
|
||||
if ($idx == $stats_count)
|
||||
{
|
||||
$max_year = substr($k, 0, 4);
|
||||
$max_month = substr($k, 5, 2);
|
||||
}
|
||||
|
||||
|
||||
$idx++;
|
||||
$total_commits += $v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$total_months = 0;
|
||||
for ($year = $min_year; $year <= $max_year; $year++)
|
||||
{
|
||||
$month = ($year == $min_year)? $min_month: 1;
|
||||
$month_end = ($year == $max_year)? $max_month: 12;
|
||||
|
||||
|
||||
while ($month <= $month_end)
|
||||
{
|
||||
$date = sprintf ("%04d-%02d", $year, $month);
|
||||
|
@ -143,6 +143,82 @@ if ( !function_exists ('codepot_delete_files'))
|
||||
}
|
||||
}
|
||||
|
||||
if ( !function_exists ('codepot_zip_dir'))
|
||||
{
|
||||
// $output_file: zip file to create
|
||||
// $path: directory to zip recursively
|
||||
// $local_path: the leading $path part is translated to $local_path
|
||||
// $exclude: file names to exclude. string or array of strings
|
||||
function codepot_zip_dir ($output_file, $path, $local_path = NULL, $exclude = NULL)
|
||||
{
|
||||
$stack = array ();
|
||||
|
||||
if (!is_dir($path)) return FALSE;
|
||||
|
||||
array_push ($stack, $path);
|
||||
$prefix = strlen($path);
|
||||
|
||||
$zip = new ZipArchive();
|
||||
if (@$zip->open ($output_file, ZipArchive::OVERWRITE) === FALSE) return FALSE;
|
||||
|
||||
while (!empty($stack))
|
||||
{
|
||||
$dir = array_pop($stack);
|
||||
|
||||
$d = @opendir ($dir);
|
||||
if ($d === FALSE) continue;
|
||||
|
||||
$new_path = empty($local_path)? $dir: substr_replace($dir, $local_path, 0, $prefix);
|
||||
if (@$zip->addEmptyDir($new_path) == FALSE)
|
||||
{
|
||||
@closedir ($dir);
|
||||
$zip->close ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//printf (">> [%s] [%s]\n", $dir, $new_path);
|
||||
while (($f = @readdir($d)) !== FALSE)
|
||||
{
|
||||
if ($f == '.' || $f == '..') continue;
|
||||
if (!empty($exclude))
|
||||
{
|
||||
$found = FALSE;
|
||||
if (is_array($exclude))
|
||||
{
|
||||
foreach ($exclude as $ex)
|
||||
{
|
||||
if (fnmatch ($ex, $f, FNM_PERIOD | FNM_PATHNAME))
|
||||
{
|
||||
$found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($found) continue;
|
||||
}
|
||||
else if (fnmatch($exclude, $f, FNM_PERIOD | FNM_PATHNAME)) continue;
|
||||
}
|
||||
|
||||
$full_path = $dir . DIRECTORY_SEPARATOR . $f;
|
||||
if (is_dir($full_path))
|
||||
{
|
||||
array_push ($stack, $full_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
$new_path = empty($local_path)? $dir: substr_replace($full_path, $local_path, 0, $prefix);
|
||||
@$zip->addFile ($full_path, $new_path);
|
||||
//printf ("[%s] [%s]\n", $full_path, $new_path);
|
||||
}
|
||||
}
|
||||
|
||||
@closedir ($dir);
|
||||
}
|
||||
|
||||
$zip->close ();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !function_exists ('codepot_find_longest_matching_sequence'))
|
||||
{
|
||||
function codepot_find_longest_matching_sequence ($old, $old_start, $old_len, $new, $new_start, $new_len)
|
||||
|
@ -921,25 +921,25 @@ class SubversionModel extends Model
|
||||
$cloc = @popen ($cloc_cmd, 'r');
|
||||
if ($cloc === FALSE)
|
||||
{
|
||||
codepot_delete_files ($actual_tfname, TRUE);
|
||||
@unlink ($tfname);
|
||||
return FALSE;
|
||||
codepot_delete_files ($actual_tfname, TRUE);
|
||||
@unlink ($tfname);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$line_count = 0;
|
||||
$cloc_data = array ();
|
||||
while (!feof($cloc))
|
||||
{
|
||||
$line = @fgets ($cloc);
|
||||
if ($line === FALSE) break;
|
||||
$line = @fgets ($cloc);
|
||||
if ($line === FALSE) break;
|
||||
|
||||
$line_count++;
|
||||
$line = trim($line);
|
||||
if ($line_count >= 3)
|
||||
{
|
||||
$counter = explode (':', $line);
|
||||
$cloc_data[$counter[1]] = array ($counter[0], $counter[2], $counter[3], $counter[4]);
|
||||
}
|
||||
$line_count++;
|
||||
$line = trim($line);
|
||||
if ($line_count >= 3)
|
||||
{
|
||||
$counter = explode (':', $line);
|
||||
$cloc_data[$counter[1]] = array ($counter[0], $counter[2], $counter[3], $counter[4]);
|
||||
}
|
||||
}
|
||||
|
||||
@pclose ($cloc);
|
||||
@ -999,6 +999,61 @@ class SubversionModel extends Model
|
||||
|
||||
return $cloc_data;
|
||||
}
|
||||
|
||||
function zipSubdir ($projectid, $path, $rev, $topdir)
|
||||
{
|
||||
$orgurl = 'file://'.$this->_canonical_path(CODEPOT_SVNREPO_DIR."/{$projectid}/{$path}");
|
||||
|
||||
$workurl = ($path == '')? $orgurl: "{$orgurl}@"; // trailing @ for collision prevention
|
||||
$info = @svn_info ($workurl, FALSE, $rev);
|
||||
if ($info === FALSE || count($info) != 1)
|
||||
{
|
||||
// If a URL is at the root of repository and the url type is file://
|
||||
// (e.g. file:///svnrepo/codepot/ where /svnrepo/codepot is a project root),
|
||||
// some versions of libsvn end up with an assertion failure like
|
||||
// ... libvvn_subr/path.c:114: svn_path_join: Assertion `svn_path_is_canonical(base, pool)' failed.
|
||||
//
|
||||
// Since the root directory is guaranteed to exist at the head revision,
|
||||
// the information can be acquired without using a peg revision.
|
||||
// In this case, a normal operational revision is used to work around
|
||||
// the assertion failure. Other functions that has to deal with
|
||||
// the root directory should implement this check to work around it.
|
||||
//
|
||||
if ($rev == SVN_REVISION_HEAD || $path == '') return FALSE;
|
||||
|
||||
// rebuild the URL with a peg revision and retry it.
|
||||
$workurl = "{$orgurl}@{$rev}";
|
||||
$info = @svn_info ($workurl, FALSE, $rev);
|
||||
if ($info === FALSE || count($info) != 1) return FALSE;
|
||||
}
|
||||
|
||||
// pass __FILE__ as the first argument so that tempnam creates a name
|
||||
// in the system directory. __FILE__ can never be a valid directory.
|
||||
$tfname = @tempnam(__FILE__, 'codepot-fetch-folder-');
|
||||
if ($tfname === FALSE) return FALSE;
|
||||
|
||||
$actual_tfname = $tfname . '.d';
|
||||
codepot_delete_files ($actual_tfname, TRUE); // delete the directory in case it exists
|
||||
|
||||
if (@svn_checkout ($workurl, $actual_tfname, $rev, 0) === FALSE)
|
||||
{
|
||||
codepot_delete_files ($actual_tfname, TRUE);
|
||||
@unlink ($tfname);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//exec ("zip {$tfname}.zip -r {$actual_tfname}");
|
||||
if (codepot_zip_dir ("{$tfname}.zip", $actual_tfname, $topdir, array('.svn')) === FALSE)
|
||||
{
|
||||
codepot_delete_files ($actual_tfname, TRUE);
|
||||
@unlink ($tfname);
|
||||
@unlink ("{$tfname}.zip"); // delete potentially residual zip file
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//codepot_delete_files ($actual_tfname, TRUE); // delete the directory in case it exists
|
||||
return $tfname;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -282,7 +282,7 @@ $this->load->view (
|
||||
|
||||
|
||||
<div class="infostrip" id="code_folder_mainarea_infostrip">
|
||||
|
||||
|
||||
<?php if (CODEPOT_SIGNIN_FOR_CODE_SEARCH === FALSE || (isset($login['id']) && $login['id'] != '')): ?>
|
||||
<?php print form_open("code/search/{$project->id}/", 'id="code_folder_search_form"')?>
|
||||
<?php print form_hidden('search_folder', set_value('search_folder', $file['fullpath']), 'id="code_folder_search_folder"')?>
|
||||
@ -350,6 +350,11 @@ $this->load->view (
|
||||
else
|
||||
print anchor ("code/history/{$project->id}/{$xpar}", $this->lang->line('History'));
|
||||
|
||||
print ' | ';
|
||||
print anchor (
|
||||
"code/fetch/{$project->id}/${xpar}{$revreq}",
|
||||
$this->lang->line('Download'));
|
||||
|
||||
print '</div>';
|
||||
|
||||
usort ($file['content'], 'comp_files');
|
||||
|
Loading…
Reference in New Issue
Block a user