Я старался изо всех сил пытаться написать скрипт непрерывной интеграции с PHP для машины Windows, на которой я работаю.
Клонировав репозиторий Git, я не смог создать скрипт, который бы все это удалил. (Папка .git и все в них). Я получаю ошибки «Отказано в доступе».
Это казалось прерывистым. Я попытался Phing, но это не удалось, но привело меня к этот билет Phing, так что я не одинок — но это решение с помощью attrib
не работает для меня
В конце концов я понял, что это просто две попытки удалить некоторые папки и / или файлы в нем. Итак, мой PHP-код, который наконец заработал, был таким:
<?php
function delTree($dir, $ignore = array()) {
// no need to continue if $dir doesn't exist
if (!file_exists($dir))
return true;
// must not continue if it's a link. trigger an error.
if (is_link($dir)) {
trigger_error("Cannot delete $dir: it's a link.", E_ERROR);
return false;
}
// if it's a file, delete it and return.
if (is_file($dir)) {
return tryUnlink($dir, 2);
}
// it's a directory. so...
// build an array of files/directories within it to delete
$files = array_diff(
scandir($dir), array('.', '..'), $ignore
);
// delete each directory within $dir
foreach ($files as $file) {
delTree("$dir/$file", $ignore);
}
// delete $dir itself
return tryRmdir($dir, 2);
}
function tryUnlink($file, $attempts = 2){
$result = unlink($file);
if (!$result) {
if ($attempts > 1){
return tryUnlink($file, $attempts--);
} else {
trigger_error("Cannot delete file $file", E_ERROR);
return false;
}
}
return true;
}
function tryRmdir($dir, $attempts = 2){
$result = rmdir($dir);
if (!$result) {
if ($attempts > 1){
return tryRmdir($dir, $attempts--);
} else {
trigger_error("Cannot delete directory $dir", E_ERROR);
return false;
}
}
return true;
}
И звать их с $attempts
аргумент, установленный на 2, решил все (12 часов спустя).
Я пробовал такие вещи, как chmod
в файл 0666
закрытие IDE, закрытие SourceTree, любых открытых окон проводника, ношение шляпы из фольги и даже вызов exec()
с такими командами, как:
rm -r .git -Force
rmdir .git /s /q
и, вероятно, еще 10, которые сейчас похоронены где-то в моем репо.
Какова могла быть причина?
Обе вы функции tryUnlink()
а также tryRmdir()
вызовет бесконечный цикл (если он на самом деле не удален). Посмотрите на следующий фрагмент + вывод.
код:
<?php
function foo ($attempts = 2) {
echo "attempts = $attempts\n";
if ($attempts > 1) {
foo ($attempts--);
} else {
echo "returning with \$attempts <= 1\n";
}
}
foo(2);
выход:
attempts = 2
attempts = 2
attempts = 2
[...many many many dupes...]
attempts = 2
attempts = 2
attempts = 2
Segmentation fault (core dumped)
Учитывая, что не сказано, что удаление вступает в силу во втором запуске.
Что касается Windows 7 (или, может быть, Vista?), Это редко, но не ненормально, чтобы первая попытка удалить дерево каталогов потерпела неудачу. Я думаю, что это из-за состояния гонки из-за удалений, обрабатываемых файловой системой асинхронно.
Как вы уже обнаружили, вы можете обойти это, повторив операцию; лично я никогда не видел, чтобы он дважды терпел неудачу, хотя я обычно позволяю ему повторить три или четыре раза, чтобы быть в безопасности.