Я вытаскиваю свои волосы, пытаясь написать сценарий непрерывной интеграции с 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 a link. trigger an error.
if (is_link($dir)) {
trigger_error("Cannot delete $dir: it a link.", E_ERROR);
return false;
}
// if it a file, delete it and return.
if (is_file($dir)) {
return tryUnlink($dir, 2);
}
// it 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)
Учитывая, что он не сказал, что удаление вторгается во второй прогон.
--$x
выполняет вычитание FIRST, а затем передает результат в качестве аргумента. $x--
передает исходное значение, затем вычитает, оставляя вычтенное значение в верхней части бесконечного стека рекурсивных вызовов. если рекурсивный вызов когда-либо вернется, то в какой-то момент вы получите attempts = 1
.
Что касается Windows 7 (или, возможно, Vista?), Это редко, но не является ненормальным, для первой попытки удалить дерево каталогов для отказа. Я думаю, что это связано с состоянием гонки из-за того, что удаления обрабатываются асинхронно файловой системой.
Как вы уже обнаружили, вы можете обойти это, повторив операцию; лично я никогда не видел, чтобы он терпел неудачу дважды подряд, хотя я обычно позволяю ему повторять три или четыре раза, чтобы быть в безопасности.
unlink()
каталог? Думал, что это было только для файлов.