@@ -166,7 +166,8 @@ class Trashbin { | |||
\OC_FileProxy::$enabled = false; | |||
$trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp; | |||
try { | |||
$sizeOfAddedFiles = self::renameRecursive('/files/'.$file_path, $trashPath, $view); | |||
$sizeOfAddedFiles = $view->filesize('/files/' . $file_path); | |||
$view->rename('/files/' . $file_path, $trashPath); | |||
} catch (\OCA\Files_Trashbin\Exceptions\CopyRecursiveException $e) { | |||
$sizeOfAddedFiles = false; | |||
if ($view->file_exists($trashPath)) { | |||
@@ -805,46 +806,6 @@ class Trashbin { | |||
return $size; | |||
} | |||
/** | |||
* recursive rename a whole directory and preserve timestamps | |||
* | |||
* @param string $source source path, relative to the users files directory | |||
* @param string $destination destination path relative to the users root directoy | |||
* @param \OC\Files\View $view file view for the users root directory | |||
* @return int | |||
* @throws Exceptions\CopyRecursiveException | |||
*/ | |||
private static function renameRecursive($source, $destination, \OC\Files\View $view) { | |||
$size = 0; | |||
if ($view->is_dir($source)) { | |||
$view->mkdir($destination); | |||
$view->touch($destination, $view->filemtime($source)); | |||
foreach ($view->getDirectoryContent($source) as $i) { | |||
$pathDir = $source . '/' . $i['name']; | |||
if ($view->is_dir($pathDir)) { | |||
$size += self::renameRecursive($pathDir, $destination . '/' . $i['name'], $view); | |||
} else { | |||
$size += $view->filesize($pathDir); | |||
$mtime = $view->filemtime($pathDir); | |||
$result = $view->rename($pathDir, $destination . '/' . $i['name']); | |||
if (!$result) { | |||
throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException(); | |||
} | |||
$view->touch($destination . '/' . $i['name'], $mtime); | |||
} | |||
} | |||
} else { | |||
$size += $view->filesize($source); | |||
$mtime = $view->filemtime($source); | |||
$result = $view->rename($source, $destination); | |||
if (!$result) { | |||
throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException(); | |||
} | |||
$view->touch($destination, $mtime); | |||
} | |||
return $size; | |||
} | |||
/** | |||
* find all versions which belong to the file we want to restore | |||
* |
@@ -511,7 +511,7 @@ class View { | |||
} | |||
} else { | |||
if ($this->is_dir($path1)) { | |||
$result = $this->copy($path1, $path2); | |||
$result = $this->copy($path1, $path2, true); | |||
if ($result === true) { | |||
$result = $storage1->rmdir($internalPath1); | |||
} | |||
@@ -519,6 +519,7 @@ class View { | |||
$source = $this->fopen($path1 . $postFix1, 'r'); | |||
$target = $this->fopen($path2 . $postFix2, 'w'); | |||
list($count, $result) = \OC_Helper::streamCopy($source, $target); | |||
$this->touch($path2, $this->filemtime($path1)); | |||
// close open handle - especially $source is necessary because unlink below will | |||
// throw an exception on windows because the file is locked | |||
@@ -556,7 +557,7 @@ class View { | |||
} | |||
} | |||
public function copy($path1, $path2) { | |||
public function copy($path1, $path2, $preserveMtime = false) { | |||
$postFix1 = (substr($path1, -1, 1) === '/') ? '/' : ''; | |||
$postFix2 = (substr($path2, -1, 1) === '/') ? '/' : ''; | |||
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); | |||
@@ -601,10 +602,13 @@ class View { | |||
} else { | |||
if ($this->is_dir($path1) && ($dh = $this->opendir($path1))) { | |||
$result = $this->mkdir($path2); | |||
if ($preserveMtime) { | |||
$this->touch($path2, $this->filemtime($path1)); | |||
} | |||
if (is_resource($dh)) { | |||
while (($file = readdir($dh)) !== false) { | |||
if (!Filesystem::isIgnoredDir($file)) { | |||
$result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file); | |||
$result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file, $preserveMtime); | |||
} | |||
} | |||
} | |||
@@ -612,6 +616,9 @@ class View { | |||
$source = $this->fopen($path1 . $postFix1, 'r'); | |||
$target = $this->fopen($path2 . $postFix2, 'w'); | |||
list($count, $result) = \OC_Helper::streamCopy($source, $target); | |||
if($preserveMtime) { | |||
$this->touch($path2, $this->filemtime($path1)); | |||
} | |||
fclose($source); | |||
fclose($target); | |||
} |
@@ -613,7 +613,7 @@ class View extends \Test\TestCase { | |||
if (\OC_Util::runningOnWindows()) { | |||
$this->markTestSkipped('[Windows] '); | |||
$depth = ((260 - $tmpdirLength) / 57); | |||
}elseif(\OC_Util::runningOnMac()){ | |||
} elseif (\OC_Util::runningOnMac()) { | |||
$depth = ((1024 - $tmpdirLength) / 57); | |||
} else { | |||
$depth = ((4000 - $tmpdirLength) / 57); | |||
@@ -806,4 +806,31 @@ class View extends \Test\TestCase { | |||
array('putFileInfo', array()), | |||
); | |||
} | |||
public function testRenameCrossStoragePreserveMtime() { | |||
$storage1 = new Temporary(array()); | |||
$storage2 = new Temporary(array()); | |||
$scanner1 = $storage1->getScanner(); | |||
$scanner2 = $storage2->getScanner(); | |||
$storage1->mkdir('sub'); | |||
$storage1->mkdir('foo'); | |||
$storage1->file_put_contents('foo.txt', 'asd'); | |||
$storage1->file_put_contents('foo/bar.txt', 'asd'); | |||
\OC\Files\Filesystem::mount($storage1, array(), '/test/'); | |||
\OC\Files\Filesystem::mount($storage2, array(), '/test/sub/storage'); | |||
$view = new \OC\Files\View(''); | |||
$time = time() - 200; | |||
$view->touch('/test/foo.txt', $time); | |||
$view->touch('/test/foo', $time); | |||
$view->touch('/test/foo/bar.txt', $time); | |||
$view->rename('/test/foo.txt', '/test/sub/storage/foo.txt'); | |||
$this->assertEquals($time, $view->filemtime('/test/sub/storage/foo.txt')); | |||
$view->rename('/test/foo', '/test/sub/storage/foo'); | |||
$this->assertEquals($time, $view->filemtime('/test/sub/storage/foo/bar.txt')); | |||
} | |||
} |