supported directory download
This commit is contained in:
parent
c8eb4f1d0d
commit
73d47592aa
@ -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')
|
||||
@ -681,36 +681,52 @@ class Code extends Controller
|
||||
flush ();
|
||||
}
|
||||
else
|
||||
{
|
||||
$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'];
|
||||
//}
|
||||
|
||||
$filename = $this->subversion->zipSubdir ($projectid, $path, $rev, $forced_name);
|
||||
if ($filename === FALSE)
|
||||
{
|
||||
$data['project'] = $project;
|
||||
$data['headpath'] = $path;
|
||||
$data['file'] = $file;
|
||||
$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';
|
||||
|
||||
$data['revision'] = $rev;
|
||||
$data['prev_revision'] =
|
||||
$this->subversion->getPrevRev ($projectid, $path, $rev);
|
||||
$data['next_revision'] =
|
||||
$this->subversion->getNextRev ($projectid, $path, $rev);
|
||||
$forced_zip_name = $forced_name . '.zip';
|
||||
|
||||
$data['readme_text'] = '';
|
||||
$data['readme_file'] = '';
|
||||
foreach (explode(',', CODEPOT_CODE_FOLDER_README) as $rf)
|
||||
{
|
||||
$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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _search_code ($project, $login)
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -983,7 +999,6 @@ class Code extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ksort ($stats);
|
||||
$stats_count = count($stats);
|
||||
$idx = 1;
|
||||
@ -1001,7 +1016,6 @@ class Code extends Controller
|
||||
$max_month = substr($k, 5, 2);
|
||||
}
|
||||
|
||||
|
||||
$idx++;
|
||||
$total_commits += $v;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -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…
x
Reference in New Issue
Block a user