supported directory download

This commit is contained in:
hyung-hwan 2015-04-14 04:11:27 +00:00
parent c8eb4f1d0d
commit 73d47592aa
4 changed files with 197 additions and 47 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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;
}
}
?>

View File

@ -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');