Автоматически удалять непереведенные файлы Subversion

Кто-нибудь знает способ рекурсивного удаления всех файлов в рабочей копии, которые не находятся под управлением версиями? (Мне нужно это, чтобы получить более надежные результаты в моей автоматической сборке VMware.)

Ответ 1

Я использую этот python script для этого:

import os
import re

def removeall(path):
    if not os.path.isdir(path):
        os.remove(path)
        return
    files=os.listdir(path)
    for x in files:
        fullpath=os.path.join(path, x)
        if os.path.isfile(fullpath):
            os.remove(fullpath)
        elif os.path.isdir(fullpath):
            removeall(fullpath)
    os.rmdir(path)

unversionedRex = re.compile('^ ?[\?ID] *[1-9 ]*[a-zA-Z]* +(.*)')
for l in  os.popen('svn status --no-ignore -v').readlines():
    match = unversionedRex.match(l)
    if match: removeall(match.group(1))

Кажется, что это хорошо работает.

Ответ 2

это работает для меня в bash:

 svn status | egrep '^\?' | cut -c8- | xargs rm

Сет Рено лучше:

svn status | grep ^\? | cut -c9- | xargs -d \\n rm -r 

Он обрабатывает неверсированные папки и пробелы в именах файлов

В соответствии с комментариями ниже, это работает только с файлами, о которых не известно о подрывной деятельности (status =?). Все, что известно о подрывной деятельности (включая Игнорируемые файлы/папки), не будет удалено.

Если вы используете subversion 1.9 или выше, вы можете просто использовать команду svn cleanup с --remove-unversioned и --remove- игнорируемые опции

Ответ 3

Я просмотрел эту страницу, пытаясь сделать то же самое, но не для автоматической сборки.

После немного более пристального взгляда я обнаружил " Расширенное контекстное меню" в TortoiseSVN. Удерживая клавишу shift, щелкните правой кнопкой мыши на рабочей копии. В меню TortoiseSVN есть дополнительные опции, в том числе: Удалить непереведенные элементы....

Хотя, возможно, не применим для этого конкретного вопроса (т.е. в контексте автоматической сборки), я подумал, что это может быть полезно для других, которые хотят сделать то же самое.

Ответ 5

Если вы находитесь в командной строке Windows,

for /f "tokens=2*" %i in ('svn status ^| find "?"') do del %i

Улучшенная версия:

for /f "usebackq tokens=2*" %i in (`svn status ^| findstr /r "^\?"`) do svn delete --force "%i %j"

Если вы используете это в пакетном файле, вам нужно удвоить значение %:

for /f "usebackq tokens=2*" %%i in (`svn status ^| findstr /r "^\?"`) do svn delete --force "%%i %%j"

Ответ 6

Я добавил это в свой профиль powershell windows

function svnclean {
    svn status | foreach { if($_.StartsWith("?")) { Remove-Item $_.substring(8) -Verbose } }
}

Ответ 7

Командная строка Linux:

svn status --no-ignore | egrep '^[?I]' | cut -c9- | xargs -d \\n rm -r

Или, если некоторые из ваших файлов принадлежат root:

svn status --no-ignore | egrep '^[?I]' | cut -c9- | sudo xargs -d \\n rm -r

Это основано на ответе Кена. (Ответ Кена пропускает игнорируемые файлы, мой ответ удаляет их).

Ответ 8

Вы не можете просто экспортировать в новое место и строить там?

Ответ 9

Просто сделайте это в unix-shell с помощью:

rm -rf `svn st . | grep "^?" | cut -f2-9 -d' '`

Ответ 10

My С# преобразование Томаса Уотнедала Питона script:

Console.WriteLine("SVN cleaning directory {0}", directory);

Directory.SetCurrentDirectory(directory);

var psi = new ProcessStartInfo("svn.exe", "status --non-interactive");
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.WorkingDirectory = directory;

using (var process = Process.Start(psi))
{
    string line = process.StandardOutput.ReadLine();
    while (line != null)
    {
        if (line.Length > 7)
        {
            if (line[0] == '?')
            {
                string relativePath = line.Substring(7);
                Console.WriteLine(relativePath);

                string path = Path.Combine(directory, relativePath);
                if (Directory.Exists(path))
                {
                    Directory.Delete(path, true);
                }
                else if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
        }
        line = process.StandardOutput.ReadLine();
    }
}

Ответ 11

Если вы используете черепаху svn, для этого есть скрытая команда. Удерживайте сдвиг, щелкнув правой кнопкой мыши по папке, чтобы запустить контекстное меню в проводнике Windows. Вы получите команду "Удалить неверсированные элементы".

см. нижнюю часть этой стр. для подробностей или снимок экрана, ниже которого выделяются расширенные функции зелеными звездами, а один представляет интерес с желтым прямоугольником...

SVN Расширенное контекстное меню и стандартное меню

Ответ 12

svn st --no-ignore  | grep '^[?I]' | sed 's/^[?I]  *//' | xargs -r -d '\n' rm -r

Это команда оболочки unix для удаления всех файлов, не находящихся под управлением subversion.

Примечания:

  • st в svn st является встроенным псевдонимом для status, то есть команда эквивалентна svn status
  • --no-ignore также включает файлы без репозитория в выводе статуса, в противном случае игнорируется с помощью таких механизмов, как .cvsignore и т.д. - поскольку цель состоит в том, чтобы иметь чистую отправную точку для сборки, этот переключатель является обязательным
  • grep фильтрует вывод таким образом, что остаются только файлы, неизвестные для подрывной операции, - строки, начинающиеся с ? файлов списка, неизвестных для подрывной операции, которые будут игнорироваться без опции --no-ignore
  • префикс до имени файла удаляется с помощью sed
  • команда xargs инструктируется через -r, чтобы не выполнить rm, когда список аргументов будет пустым
  • параметр -d '\n' сообщает xargs использовать новую строку как разделитель, так что эта команда также работает для имен файлов с пробелами
  • rm -r используется в случае, если необходимо удалить полные каталоги (которые не являются частью репозитория)

Ответ 13

Если у вас есть TortoiseSVN на вашем пути, и вы находитесь в правильном каталоге:

TortoiseProc.exe /command:cleanup /path:"%CD%" /delunversioned /delignored /nodlg /noui

Параметры описаны в справке TortoiseSVN для /command:cleanup:

Используйте/noui, чтобы предотвратить появление диалогового окна результатов либо сообщая о завершении очистки, либо показывая ошибку сообщение)./noprogressui также отключает диалог прогресса. /nodlg отключает отображение диалогового окна очистки, в котором пользователь может выбрать, что точно следует делать при очистке. Доступные действия могут быть с параметрами/очисткой для очистки состояния, /revert, /delunversioned,/delignored,/refreshshell и /externals.

Ответ 14

Я не мог заставить любой из вышеперечисленных работать без дополнительных зависимостей, которые я не хотел добавлять в свою автоматическую систему сборки на win32. Поэтому я собрал следующие команды Ant - обратите внимание, что для них требуется установить Ant -contrib JAR (я использовал последнюю версию версии 1.0b3 с Ant 1.7.0).

Примечание. Это исключает все неверсированные файлы без предупреждения.

  <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
  <taskdef name="for" classname="net.sf.antcontrib.logic.ForTask" />

  <macrodef name="svnExecToProperty">
    <attribute name="params" />
    <attribute name="outputProperty" />
    <sequential>
      <echo message="Executing Subversion command:" />
      <echo message="  svn @{params}" />
      <exec executable="cmd.exe" failonerror="true"
            outputproperty="@{outputProperty}">
        <arg line="/c svn @{params}" />
      </exec>
    </sequential>
  </macrodef>

  <!-- Deletes all unversioned files without warning from the 
       basedir and all subfolders -->
  <target name="!deleteAllUnversionedFiles">
    <svnExecToProperty params="status &quot;${basedir}&quot;" 
                       outputProperty="status" />
    <echo message="Deleting any unversioned files:" />
    <for list="${status}" param="p" delimiter="&#x0a;" trim="true">
      <sequential>
        <if>
          <matches pattern="\?\s+.*" string="@{p}" />
          <then>
            <propertyregex property="f" override="true" input="@{p}" 
                           regexp="\?\s+(.*)" select="\1" />
            <delete file="${f}" failonerror="true" />
          </then>
        </if>
      </sequential>
    </for>
    <echo message="Done." />
  </target>

Для другой папки измените ссылку ${basedir}.

Ответ 15

svn status --no-ignore | awk '/^[I\?]/ {system("echo rm -r " $2)}'

удалите эхо, если это точно, что вы хотите сделать.

Ответ 16

Так как все остальные делают это...

svn status | grep ^? | awk '{print $2}' | sed 's/^/.\//g' | xargs rm -R

Ответ 17

Возможно также внести еще один вариант

svn status | awk '{if($2 !~ /(config|\.ini)/ && !system("test -e \"" $2 "\"")) {print $2; system("rm -Rf \"" $2 "\"");}}'

/(config|.ini)/для моих целей.

И может быть хорошей идеей добавить --no-ignore в команду svn

Ответ 19

Чистое решение cmd/bat для windows:

@echo off

svn cleanup .
svn revert -R .
For /f "tokens=1,2" %%A in ('svn status --no-ignore') Do (
     If [%%A]==[?] ( Call :UniDelete %%B
     ) Else If [%%A]==[I] Call :UniDelete %%B
   )
svn update .
goto :eof

:UniDelete delete file/dir
if "%1"=="%~nx0" goto :eof
IF EXIST "%1\*" ( 
    RD /S /Q "%1"
) Else (
    If EXIST "%1" DEL /S /F /Q "%1"
)
goto :eof

Ответ 20

Я пробовал версию от Сета Рено из этого ответа, но это не сработало для меня. У меня было 8 символов перед именем файла, а не 9 в cut -c9-.

Итак, это моя версия с sed вместо cut:

svn status | grep ^\? | sed -e 's/\?\s*//g' | xargs -d \\n rm -r

Ответ 21

Если вы классные с PowerShell:

svn status --no-ignore | ?{$_.SubString(0,1).Equals("?")} | foreach { remove-item -Path (join-Path .\ $_.Replace("?","").Trim()) -WhatIf }

Выньте флаг -WhatIf, чтобы команда действительно выполняла удаление. В противном случае он просто выведет, что он будет делать, если запускается без -WhatIf.

Ответ 22

Для людей, которым нравится делать это с помощью perl вместо python, оболочки Unix, java и т.д. Таким образом, небольшой perl script, который также делает стрелу.

Примечание. Это также удаляет все неверсированные каталоги

#!perl

use strict;

sub main()

{

    my @unversioned_list = `svn status`;

    foreach my $line (@unversioned_list)

    {

        chomp($line);

        #print "STAT: $line\n";

        if ($line =~/^\?\s*(.*)$/)

        {

            #print "Must remove $1\n";

            unlink($1);

            rmdir($1);

        }

    }

}

main();

Ответ 23

Если вы не хотите писать какой-либо код, svn2.exe из svn2svn делает это, также есть статью о том, как она реализована. Удаленные папки и файлы помещаются в корзину.

Запустите "svn2.exe sync [путь]".

Ответ 25

Чистым способом сделать это в PERL будет:

#!/usr/bin/perl
use IO::CaptureOutput 'capture_exec'

my $command = sprintf ("svn status --no-ignore | grep '^?' | sed -n 's/^\?//p'");

my ( $stdout, $stderr, $success, $exit_code ) = capture_exec ( $command );
my @listOfFiles = split ( ' ', $stdout );

foreach my $file ( @listOfFiles )
{ # foreach ()
    $command = sprintf ("rm -rf %s", $file);
    ( $stdout, $stderr, $success, $exit_code ) = capture_exec ( $command );
} # foreach ()

Ответ 26

Я использовал ~ 3 часа, чтобы сгенерировать это. Это займет 5 минут, чтобы сделать это в Unix. Основная проблема: пробелы в именах для папок Win, невозможность редактирования %% я и проблема с определением vars в цикле Win cmd.

setlocal enabledelayedexpansion

for /f "skip=1 tokens=2* delims==" %%i in ('svn status --no-ignore --xml ^| findstr /r "path"') do (
@set j=%%i
@rd /s /q !j:~0,-1!
)

Ответ 27

Снайпер кода С# выше не работал у меня - у меня есть клиент черепахи svn, а строки отформатированы немного по-разному. Вот тот же самый код snipet, что и выше, только перезаписан для работы и использования regex.

        /// <summary>
    /// Cleans up svn folder by removing non committed files and folders.
    /// </summary>
    void CleanSvnFolder( string folder )
    {
        Directory.SetCurrentDirectory(folder);

        var psi = new ProcessStartInfo("svn.exe", "status --non-interactive");
        psi.UseShellExecute = false;
        psi.RedirectStandardOutput = true;
        psi.WorkingDirectory = folder;
        psi.CreateNoWindow = true;

        using (var process = Process.Start(psi))
        {
            string line = process.StandardOutput.ReadLine();
            while (line != null)
            {
                var m = Regex.Match(line, "\\? +(.*)");

                if( m.Groups.Count >= 2 )
                {
                    string relativePath = m.Groups[1].ToString();

                    string path = Path.Combine(folder, relativePath);
                    if (Directory.Exists(path))
                    {
                        Directory.Delete(path, true);
                    }
                    else if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                }
                line = process.StandardOutput.ReadLine();
            }
        }
    } //CleanSvnFolder

Ответ 28

Для людей в Windows, которые хотят избежать использования какого-либо инструмента, кроме стандартных команд MS-Dos, здесь:

FOR/F "tokens = 1 * delims =" % G IN ('svn st ^ | findstr "^?" ') DO rd/s/q "% H"

FOR/F "tokens = 1 * delims =" % G IN ('svn st ^ | findstr "^?" ') DO del/s/f/q "% H"

  • svn st будет отображать статус каждого файла и папки в рабочей копии
  • findstr будет искать каждую строку, начинающуюся с '?', что означает, что файл/папка не вернулась.
  • FOR будет использоваться в качестве разделителей и взять маркеры после 1-го (первый -% G, остальное -% H) Таким образом, мы выделяем файл/папку из вывода команды svn st.
  • rd удалит папки, del удалит файлы.

Ответ 29

Я бы добавил это в качестве комментария к ответу Томаса Ундедала, но пока не могу.

Небольшая проблема с ним (что не повлияет на Windows) заключается в том, что он проверяет только файлы или каталоги. Для Unix-подобных систем, где могут присутствовать символические ссылки, необходимо изменить строку:

if os.path.isfile(fullpath):

к

if os.path.isfile(fullpath) or os.path.islink(fullpath):

чтобы удалить ссылки.

Для меня, изменив последнюю строку if match: removeall(match.group(1)) на

    if match:
        print "Removing " + match.group(1)
        removeall(match.group(1))

так что он отображает то, что он удаляет, тоже полезно.

В зависимости от используемого варианта часть ?[\?ID] регулярного выражения может быть лучше как ?[\?I], так как D также удаляет удаленные файлы, которые находились под контролем версий. Я хочу использовать это для сборки в чистой, проверенной папке, поэтому в состоянии D не должно быть файлов.