Supprimer automatiquement les fichiers non versionnés de Subversion


111

Quelqu'un connaît-il un moyen de supprimer récursivement tous les fichiers d'une copie de travail qui ne sont pas sous contrôle de version? (J'en ai besoin pour obtenir des résultats plus fiables dans ma version automatique de VMware.)


7
Je suis un utilisateur SVN et j'ai comparé Git à SVN pour voir si je veux éventuellement faire le changement. il semble que cela puisse être un autre exemple où Git brille avec sa commande "git clean".
jpierson

3
Ou hg purge --alldans Mercurial.
Brendan Long

Duplicata de stackoverflow.com/questions/2803823/… où il y a beaucoup plus d'activité utile.
Heath Raftery

Réponses:


26

Éditer:

Subversion 1.9.0 a introduit une option pour ce faire:

svn cleanup --remove-unversioned

Avant cela, j'utilise ce script python pour faire cela:

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))

Il semble bien faire le travail.


1
Fonctionne toujours pour moi avec Python 2.7.2. Warren P: Pouvez-vous fournir plus de détails?
Thomas Watnedal

Je pense que c'était juste un problème avec Python 2.6. Fonctionne à nouveau pour moi en 2.7.
Warren P

1
Downvote: L'autre solution ci svn cleanup --remove-unversioned- dessous est meilleure. Et c'est pour Subversion 1.9.0 (cette version date de 2015). Il est stable et standard.
tres.14159

138

cela fonctionne pour moi en bash:

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

Seth Reno est meilleur:

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

Il gère les dossiers et les espaces non versionnés dans les noms de fichiers

Comme indiqué ci-dessous, cela ne fonctionne que sur les fichiers que subversion ne connaît pas (status =?) Tout ce que la subversion ne sait au sujet (y compris les fichiers / dossiers Ignoré) ne seront pas supprimés.

Si vous utilisez subversion 1.9 ou supérieur, vous pouvez simplement utiliser la commande svn cleanup avec les options --remove-unversioned et --remove-ignored


6
Également utilisable sous Windows dans cygwin.
Honza

9
Vous pouvez envisager d'ajouter l'option -d à xargs pour les noms de fichiers avec des espaces et l'option -r à rm pour tous les répertoires ajoutés: svn status | grep ^ \? | couper -c9- | xargs -d \\ n rm -r
Seth Reno

4
J'ai également eu des problèmes avec l'option -d fonctionnant sous OS X, mon alternative est la suivante, qui traduit les sauts de ligne en caractères nuls et utilise l'option -0 sur xargs pour gérer les espaces dans les noms de fichiers: svn status | grep ^ \? | couper -c9- | tr '\ n' '\ 0' | xargs -0 rm
Brian Webster

3
Si vous froncez les sourcils sur les commandes qui reposent sur le nombre exact de caractères dans la sortie d'une autre commande:svn status | grep "^?" | awk '{print $2}' | xargs -d \\n rm -r
Michael Schlottke-Lakemper

3
@Pavel Jetez un œil à l'option xargs --no-run-if-empty
Ken

71

J'ai parcouru cette page en cherchant à faire la même chose, mais pas pour une construction automatisée.

Après un peu plus de recherche, j'ai découvert le « Menu contextuel étendu » dans TortoiseSVN. Maintenez la touche Maj enfoncée et faites un clic droit sur la copie de travail. Il y a maintenant des options supplémentaires dans le menu TortoiseSVN, y compris « Supprimer les éléments non versionnés ... ».

Bien que peut-être pas applicable pour cette question spécifique (c'est-à-dire dans le contexte d'une construction automatisée), j'ai pensé que cela pourrait être utile pour d'autres qui cherchent à faire la même chose.


Génial! Sous XP, cela ne fonctionne que dans la vue liste (côté droit de l'explorateur) et non dans l'arborescence (côté gauche).
Christopher Oezbek le

Fantastique, ne l'envoyer qu'à la corbeille, ce serait bien de faire une suppression directe. Juste ce dont j'avais besoin.
Dean Thomas

Vous pouvez également automatiser cela sur la ligne de commande avec TortoiseProc.exe de TortoiseSVN: détails dans ma réponse ci-dessous.
stevek_mcc


9

Si vous êtes sur la ligne de commande Windows,

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

Version améliorée:

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

Si vous l'utilisez dans un fichier de commandes, vous devez doubler %:

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

1
Ce genre a fonctionné pour moi. Semblait s'étouffer avec certains dossiers non versionnés.
jpierson

7

J'ai ajouté ceci à mon profil Windows PowerShell

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

2
@FelipeAlvarez Oui. Oui. Ce n'est pas la meilleure chose depuis le pain tranché, mais il bat le lot. Je dirais que c'est au moins aussi utile que bash, probablement un peu plus puisque vous pouvez extraire des assemblys .NET.
jpmc26

Il souffre de la tendance abominable de Microsoft à la verbosité (pas seulement dans la longueur du nom de la commande, mais dans l'impossibilité générale de faire quoi que ce soit sans copier des extraits géants d'Internet), mais c'est incroyablement utile et plutôt bien pensé.
Warren P

1
Vous voudrez peut-être ajouter --no-ignoreà svn statuset -RecurseàRemove-Item
Kevin Smyth

5

Ligne de commande Linux:

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

Ou, si certains de vos fichiers appartiennent à root:

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

Ceci est basé sur la réponse de Ken. (La réponse de Ken ignore les fichiers ignorés; ma réponse les supprime).


5

Faites-le simplement sur un shell unix avec:

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

Cela ne fonctionne pas si le nombre de fichiers à supprimer dépasse le nombre maximal d'arguments de ligne de commande. Voir aussi les réponses basées sur les xargs.
maxschlepzig

4

Ne pouvez-vous pas simplement effectuer une exportation vers un nouvel emplacement et créer à partir de là?


1
Pour une version automatisée, je voudrais une exportation propre.
g.

1
Idéalement, vous feriez cela, mais cela pose problème si votre paiement est très important. C'est probablement la raison pour laquelle l'OP a demandé: raccourcir la construction.
jpmc26

4

Si vous avez TortoiseSVN sur votre chemin et que vous êtes dans le bon répertoire:

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

Les options sont décrites dans l'aide de TortoiseSVN pour /command:cleanup:

Utilisez / noui pour empêcher la boîte de dialogue de résultat de s'afficher, indiquant que le nettoyage est terminé ou affichant un message d'erreur). / noprogressui désactive également la boîte de dialogue de progression. / nodlg désactive l'affichage de la boîte de dialogue de nettoyage dans laquelle l'utilisateur peut choisir exactement ce qui doit être fait lors du nettoyage. Les actions disponibles peuvent être spécifiées avec les options / cleanup pour le nettoyage de l'état, / revert, / delunversioned, / delignored, / refreshshell et / externals.


4

Si vous utilisez tortoise svn, il existe une commande cachée pour le faire. Maintenez la touche Maj enfoncée tout en cliquant avec le bouton droit sur un dossier pour lancer le menu contextuel dans l'explorateur Windows. Vous obtiendrez une commande "Supprimer les éléments non versionnés".

voir le bas de cette page pour plus de détails, ou la capture d'écran ci-dessous qui met en évidence les fonctionnalités étendues avec les étoiles vertes, et celle d'intérêt avec le rectangle jaune ...

Menu contextuel étendu SVN vs menu standard



3

Ma conversion C # du script Python de Thomas Watnedals:

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();
    }
}

Je préférerais déplacer les fichiers non versionnés, juste au cas où vous en auriez besoin plus tard.
leppie

Sur une machine de développement, bien sûr - mais dans la version de VMware, cela n'aurait aucun sens car personne ne s'y connecte et ne crée des fichiers.
Stefan Schultze

Merci, je l'ai utilisé dans le cadre de mon script MSBuild dans cruisecontrol pour nettoyer mon répertoire source avant les builds
gregmac

Commencé en fonction de votre code et est allé plus loin: github.com/tgmayfield/svn-clean-sharp/downloads
Tom Mayfield

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

Il s'agit d'une commande shell unix pour supprimer tous les fichiers non sous contrôle subversion.

Remarques:

  • l' sten svn stest une accumulation dans l' alias pour status, soit la commande est équivalente àsvn status
  • --no-ignoreinclut également les fichiers non référentiels dans la sortie de statut, sinon ignore via des mécanismes comme .cvsignoreetc. - puisque le but est d'avoir un point de départ propre pour les builds, ce commutateur est indispensable
  • les grepfiltres la sortie de telle sorte que seuls les fichiers inconnus de subversion restent - les lignes commençant par la ?liste des fichiers inconnus de subversion qui seraient ignorés sans l' --no-ignoreoption
  • le préfixe jusqu'au nom de fichier est supprimé via sed
  • la xargscommande reçoit l'instruction -rde ne pas s'exécuter rm, lorsque la liste d'arguments serait vide
  • l' -d '\n'option indique xargsd'utiliser une nouvelle ligne comme délimiteur, la commande fonctionne également pour les noms de fichiers avec des espaces
  • rm -r est utilisé dans le cas où des répertoires complets (qui ne font pas partie du référentiel) doivent être supprimés

2

Je ne pouvais pas faire fonctionner l'un des éléments ci-dessus sans dépendances supplémentaires que je ne voulais pas avoir à ajouter à mon système de construction automatisé sur win32. J'ai donc rassemblé les commandes Ant suivantes - notez que celles-ci nécessitent l'installation du JAR Ant-contrib (j'utilisais la version 1.0b3, la dernière, avec Ant 1.7.0).

Notez que cela supprime tous les fichiers non versionnés sans avertissement.

  <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>

Pour un autre dossier, modifiez la ${basedir}référence.


1
Remarque: supprime uniquement les fichiers non versionnés; ne supprime pas les dossiers vides non versionnés.

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

supprimez l'écho si vous êtes sûr de ce que vous voulez faire.


1
Ceci est inférieur aux réponses basées sur xargs car pour n fichiers supprimés, il y a n /bin/shet n rmprocessus fourchus.
maxschlepzig

D'accord. Merci pour les informations xargs.
Aria

2

Puisque tout le monde le fait ...

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

1

Pourrait aussi bien apporter une autre option

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

Le /(config|.ini)/ est pour mes propres besoins.

Et peut-être une bonne idée d'ajouter --no-ignore à la commande svn



1

Solution pure Windows cmd / bat:

@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

En fait, ce script n'a pas supprimé mes fichiers. Peut-être à cause des espaces qu'il contient. La réponse en une ligne de @SukeshNambiar a fonctionné.
Christiaan Westerbeek

1

J'ai essayé la version de Seth Reno à partir de cette réponse, mais cela n'a pas fonctionné pour moi. J'ai eu 8 caractères avant le nom de fichier, pas 9 utilisés dans cut -c9-.

Voici donc ma version avec sedau lieu de cut:

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

1

Si vous êtes cool avec PowerShell:

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

Retirez l'indicateur -WhatIf pour que la commande effectue réellement les suppressions. Sinon, il affichera simplement ce qu'il ferait s'il était exécuté sans l'option -WhatIf.


1

J'ajouterais ceci en commentaire à la réponse de Thomas Watnedal , mais je ne peux pas encore.

Un problème mineur (qui n'affectera pas Windows) est qu'il ne vérifie que les fichiers ou les répertoires. Pour les systèmes de type Unix où des liens symboliques peuvent être présents, il est nécessaire de changer la ligne:

if os.path.isfile(fullpath):

à

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

pour supprimer également les liens.

Pour moi, changer la dernière ligne if match: removeall(match.group(1))en

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

afin qu'il affiche ce qu'il supprime était également utile.

Selon le cas d'utilisation, la ?[\?ID]partie de l'expression régulière peut être meilleure car ?[\?I], car le Dsupprime également les fichiers supprimés, qui étaient sous contrôle de version. Je veux l'utiliser pour créer un dossier propre et archivé, il ne devrait donc y avoir aucun fichier dans un Détat.


1

@zhoufei J'ai testé votre réponse et voici la version mise à jour:

FOR /F "tokens=1* delims= " %%G IN ('svn st %~1 ^| findstr "^?"') DO del /s /f /q "%%H"
FOR /F "tokens=1* delims= " %%G IN ('svn st %~1 ^| findstr "^?"') DO rd /s /q "%%H"
  • Vous devez utiliser deux %marques devant G et H
  • Changez l'ordre: supprimez d'abord tous les fichiers, puis supprimez tous les répertoires
  • (facultatif :) Au lieu de %~1peut être utilisé n'importe quel nom de répertoire, je l'ai utilisé comme une fonction dans un fichier chauve-souris, de même que le %~1premier paramètre d'entrée

0

Si vous ne voulez pas écrire de code, svn2.exe de svn2svn le fait, il y a aussi un article sur la façon dont il est implémenté. Les dossiers et fichiers supprimés sont placés dans la corbeille.

Exécutez "svn2.exe sync [chemin]".


0

Pour les gens qui aiment faire cela avec perl au lieu de python, shell Unix, java, etc. Voici un petit script perl qui fait aussi le jib.

Remarque: cela supprime également tous les répertoires non versionnés

#!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();


0

Une manière propre de faire cela dans PERL serait:

#!/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 ()

0

J'ai utilisé ~ 3 heures pour générer cela. Cela prendrait 5 minutes pour le faire sous Unix. Le problème principal était: les espaces dans les noms pour les dossiers Win, l'impossibilité d'éditer %% i et le problème de la définition des variables dans la boucle 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!
)

0

L'extrait de code C # ci-dessus n'a pas fonctionné pour moi - j'ai le client tortoise svn, et les lignes sont formatées légèrement différemment. Voici le même extrait de code que ci-dessus, réécrit uniquement pour fonctionner et utiliser 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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.