Secara otomatis menghapus file tidak berversi Subversion

111

Adakah yang tahu cara untuk secara rekursif menghapus semua file dalam copy pekerjaan yang tidak di bawah kendali versi? (Saya membutuhkan ini untuk mendapatkan hasil yang lebih andal dalam VMware build otomatis saya.)

Stefan Schultze
sumber
7
Saya pengguna SVN dan telah membandingkan Git dengan SVN untuk mengetahui apakah saya akhirnya ingin beralih. sepertinya ini adalah contoh lain di mana Git bersinar dengan perintah "git clean".
jpierson
3
Atau hg purge --alldi Mercurial.
Brendan Long
Duplikat stackoverflow.com/questions/2803823/… di mana terdapat lebih banyak aktivitas berguna.
Heath Raftery

Jawaban:

26

Edit:

Subversion 1.9.0 memperkenalkan opsi untuk melakukan ini:

svn cleanup --remove-unversioned

Sebelum itu, saya menggunakan skrip python ini untuk melakukan itu:

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

Tampaknya melakukan pekerjaan dengan cukup baik.

Thomas Watnedal
sumber
1
Masih berfungsi untuk saya dengan Python 2.7.2. Warren P: Bisakah Anda memberikan rincian lebih lanjut?
Thomas Watnedal
Saya pikir itu hanya masalah dengan Python 2.6. Bekerja lagi untuk saya di 2.7.
Warren P
1
Tidak suka: Solusi lain dari bawah svn cleanup --remove-unversionedlebih baik. Dan untuk Subversion 1.9.0 (versi ini dari 2015). Ini stabil dan standar.
tres. 14159
138

ini bekerja untuk saya di pesta:

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

Seth Reno lebih baik:

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

Ini menangani folder dan spasi tidak berversi dalam nama file

Sesuai dengan komentar di bawah, ini hanya bekerja pada file yang subversi tidak tahu tentang (status =?). Apa pun yang subversi tidak tahu tentang (termasuk Diabaikan file / folder) tidak akan dihapus.

Jika Anda menggunakan subversi 1.9 atau lebih tinggi, Anda dapat menggunakan perintah pembersihan svn dengan opsi --remove-unversioned dan --remove-ignored

Ken
sumber
6
Juga dapat digunakan di Windows di cygwin.
Honza
9
Anda dapat mempertimbangkan untuk menambahkan opsi -d ke xargs untuk nama file dengan spasi dan opsi -r ke rm untuk direktori yang ditambahkan: status svn | grep ^ \? | potong -c9- | xargs -d \\ n rm -r
Seth Reno
4
Saya juga mengalami masalah dengan opsi -d yang berjalan di OS X, alternatif saya adalah sebagai berikut, yang menerjemahkan linebreak menjadi karakter null dan menggunakan opsi -0 pada xargs untuk menangani spasi dalam nama file: status svn | grep ^ \? | potong -c9- | tr '\ n' '\ 0' | xargs -0 rm
Brian Webster
3
Jika Anda tidak menyukai perintah yang mengandalkan jumlah karakter yang tepat dalam output dari perintah lain:svn status | grep "^?" | awk '{print $2}' | xargs -d \\n rm -r
Michael Schlottke-Lakemper
3
@Pavel Lihatlah xargs - opsi tidak-lari-jika-kosong
Ken
71

Saya berlari melintasi halaman ini sambil mencari untuk melakukan hal yang sama, meskipun bukan untuk pembuatan otomatis.

Setelah mencari lebih banyak, saya menemukan ' Menu Konteks yang Diperluas ' di TortoiseSVN. Tahan tombol shift dan klik kanan pada copy pekerjaan. Sekarang ada opsi tambahan di bawah menu TortoiseSVN termasuk ' Hapus item tidak berversi ... '.

Meskipun mungkin tidak berlaku untuk pertanyaan khusus ini (yaitu dalam konteks pembuatan otomatis), saya pikir ini mungkin berguna bagi orang lain yang ingin melakukan hal yang sama.

g.
sumber
Bagus! Di XP, ini hanya bekerja dalam tampilan daftar (sisi kanan penjelajah) bukan dalam tampilan pohon (sisi kiri).
Christopher Oezbek
Hebat, kirim saja ke recycle bin, alangkah baiknya melakukan hapus langsung. Hanya apa yang saya butuhkan.
Dean Thomas
Anda juga bisa mengotomatiskan ini pada baris perintah dengan TortoiseProc.exe TortoiseSVN: detail dalam jawaban saya di bawah ini.
stevek_mcc
19

Lihat: svn-clean

Martin
sumber
Hadir di cygwin dalam paket subversion-tools .
bobbogo
Dan di Ubuntu, dalam paket yang sama: subversion-tools .
Tim
Ini juga menghapus repositori bersarang.
Serge Rogatch
9

Jika Anda menggunakan baris perintah windows,

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

Versi yang ditingkatkan:

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

Jika Anda menggunakan ini dalam file batch, Anda perlu menggandakan %:

for /f "usebackq tokens=2*" %%i in (`svn status ^| findstr /r "^\?"`) do svn delete --force "%%i %%j"
Sukesh Nambiar
sumber
1
Ini agak berhasil untuk saya. Tampaknya tersedak beberapa folder tidak berversi sekalipun.
jpierson
7

Saya menambahkan ini ke profil windows PowerShell saya

function svnclean {
    svn status | foreach { if($_.StartsWith("?")) { Remove-Item $_.substring(8) -Verbose } }
}
Kyle
sumber
2
@Papua Ya, kami melakukannya. Ini bukan hal terhebat sejak roti iris, tapi ini mengalahkan tumpukan. Saya akan mengatakan itu setidaknya berguna seperti bash, mungkin sedikit lebih berguna karena Anda dapat menarik rakitan .NET.
jpmc26
Itu menderita kecenderungan keji dari microsoft terhadap verbositas (tidak hanya dalam panjang nama perintah, tetapi secara keseluruhan ketidakmungkinan menyelesaikan sesuatu tanpa menyalin potongan raksasa dari internet), tetapi itu sangat berguna, dan cukup dipikirkan dengan baik.
Warren P
1
Anda mungkin ingin menambah --no-ignoreke svn statusdan -RecursekeRemove-Item
Kevin Smyth
5

Baris perintah Linux:

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

Atau, jika beberapa file Anda dimiliki oleh root:

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

Ini berdasarkan jawaban Ken. (Jawaban Ken melewatkan file yang diabaikan; jawaban saya menghapusnya).

pengguna9876
sumber
5

Lakukan saja di unix-shell dengan:

rm -rf `svn st . | grep "^?" | cut -f2-9 -d' '`
bruziuz
sumber
Ini tidak berfungsi jika jumlah file yang akan dihapus melebihi jumlah maksimal argumen baris perintah. Lihat juga jawaban berbasis xargs.
maxschlepzig
4

Bisakah Anda tidak hanya melakukan ekspor ke lokasi baru dan membangun dari sana?

leppie
sumber
1
Untuk pembuatan otomatis, saya ingin ekspor bersih.
g.
1
Idealnya, Anda akan melakukan ini, tetapi ini bermasalah jika pembayaran Anda sangat besar. Mungkin itulah alasan OP bertanya: untuk mempersingkat build.
jpmc26
4

Jika Anda memiliki TortoiseSVN di jalur Anda dan Anda berada di direktori yang benar:

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

Opsi dijelaskan dalam bantuan TortoiseSVN untuk /command:cleanup:

Gunakan / noui untuk mencegah dialog hasil bermunculan baik yang memberi tahu tentang pembersihan yang selesai atau menampilkan pesan kesalahan). / noprogressui juga menonaktifkan dialog kemajuan. / nodlg menonaktifkan menampilkan dialog pembersihan di mana pengguna dapat memilih apa yang harus dilakukan dalam pembersihan. Tindakan yang tersedia dapat dispesifikasikan dengan opsi / pembersihan untuk pembersihan status, / kembali, / delunversioned, / delignored, / refreshshell dan / externals.

stevek_mcc
sumber
4

Jika Anda menggunakan tortoise svn, ada perintah tersembunyi untuk melakukan ini. Tahan shift sambil mengklik kanan pada folder untuk meluncurkan menu konteks di windows explorer. Anda akan mendapatkan perintah "Hapus Item Tidak Berversi".

lihat bagian bawah halaman ini untuk detailnya, atau cuplikan layar di bawah ini yang menyoroti fitur tambahan dengan bintang hijau, dan salah satu yang menarik dengan persegi panjang kuning ...

SVN Menu konteks diperpanjang vs menu standar

rob bentley
sumber
3

Konversi C # saya dari skrip Thomas Watnedals Python:

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();
    }
}
Stefan Schultze
sumber
Saya lebih suka memindahkan file tidak berversi, kalau-kalau Anda membutuhkannya di suatu tempat nanti.
leppie
Pada mesin pengembangan, tentu saja - tetapi dalam build VMware, hal itu tidak masuk akal karena tidak ada yang masuk ke dalamnya dan membuat file.
Stefan Schultze
Terima kasih, saya menggunakan ini sebagai bagian dari skrip MSBuild saya di cruisecontrol untuk membersihkan direktori sumber saya sebelum membangun
gregmac
Dimulai berdasarkan kode Anda dan melangkah lebih jauh: 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

Ini adalah perintah shell unix untuk menghapus semua file yang tidak berada di bawah kendali subversi.

Catatan:

  • yang stdi svn stadalah build-in alias untuk status, yaitu perintah setara dengansvn status
  • --no-ignorejuga menyertakan file non-repositori dalam output status, jika tidak mengabaikan melalui mekanisme seperti .cvsignoredll. - karena tujuannya adalah untuk memiliki titik awal yang bersih untuk build, sakelar ini adalah suatu keharusan
  • yang grepfilter output sehingga hanya file yang tidak diketahui untuk subversi yang tersisa - garis dimulai dengan ?daftar file yang tidak diketahui untuk subversi yang akan diabaikan tanpa --no-ignoreopsi
  • awalan hingga nama file dihapus melalui sed
  • yang xargsperintah diinstruksikan melalui -runtuk tidak mengeksekusi rm, ketika daftar argumen akan kosong
  • yang -d '\n'pilihan memberitahu xargsuntuk menggunakan baris baru sebagai pembatas perintah tersebut juga bekerja untuk nama file dengan spasi
  • rm -r digunakan jika direktori lengkap (yang bukan bagian dari repositori) perlu dihapus
maxschlepzig
sumber
2

Saya tidak bisa mendapatkan semua hal di atas untuk bekerja tanpa ketergantungan tambahan. Saya tidak ingin menambahkan ke sistem build otomatis saya di win32. Jadi saya mengumpulkan perintah Ant berikut - perhatikan ini memerlukan Ant-contrib JAR untuk diinstal (saya menggunakan versi 1.0b3, yang terbaru, dengan Ant 1.7.0).

Perhatikan ini menghapus semua file tidak berversi tanpa peringatan.

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

Untuk folder lain, ubah ${basedir}referensinya.


sumber
1
Catatan: hanya menghapus file tidak berversi; tidak menghapus folder kosong tidak berversi.
2
svn status --no-ignore | awk '/^[I\?]/ {system("echo rm -r " $2)}'

hapus gema jika Anda yakin itu yang ingin Anda lakukan.

Aria
sumber
1
Ini lebih rendah daripada jawaban berbasis xargs karena untuk n file yang akan dihapus ada n /bin/shdan n rmproses bercabang.
maxschlepzig
Sepakat. Terima kasih atas info xargs.
Aria
2

Karena semua orang melakukannya ...

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

Mungkin juga menyumbangkan opsi lain

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

/(Configi>.ini)/ untuk tujuan saya sendiri.

Dan mungkin ide yang bagus untuk menambahkan --no-ignore ke perintah svn

pengguna1299374
sumber
1

Solusi cmd / bat windows murni:

@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
Andriy F.
sumber
Sebenarnya skrip ini tidak menghapus file saya. Mungkin karena adanya ruang di dalamnya. Jawaban satu baris oleh @SukeshNambiar berhasil.
Christiaan Westerbeek
1

Saya sudah mencoba versi Seth Reno dari jawaban ini tetapi tidak berhasil untuk saya. Saya memiliki 8 karakter sebelum nama file, bukan 9 yang digunakan dalam cut -c9-.

Jadi ini versi saya dengan sedalih - alih cut:

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

Jika Anda keren dengan PowerShell:

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

Keluarkan flag -WhatIf untuk membuat perintah benar-benar melakukan penghapusan. Jika tidak, itu hanya akan menampilkan apa yang akan dilakukannya jika dijalankan tanpa -WhatIf.

Giscard Biamby
sumber
1

Saya akan menambahkan ini sebagai komentar untuk jawaban Thomas Watnedal , tetapi belum bisa.

Masalah kecil dengannya (yang tidak akan mempengaruhi Windows) adalah ia hanya memeriksa file atau direktori. Untuk sistem mirip Unix di mana tautan simbolik mungkin ada, perlu untuk mengubah baris:

if os.path.isfile(fullpath):

untuk

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

untuk juga menghapus tautan.

Bagi saya, mengubah baris terakhir if match: removeall(match.group(1))menjadi

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

sehingga menampilkan apa yang dihapusnya juga berguna.

Bergantung pada kasus penggunaan, ?[\?ID]bagian dari ekspresi reguler mungkin lebih baik ?[\?I], karena Djuga menghapus file yang dihapus, yang berada di bawah kontrol versi. Saya ingin menggunakan ini untuk membangun di folder yang bersih dan sudah diperiksa, jadi seharusnya tidak ada file dalam Dkeadaan.

Michael Firth
sumber
1

@zhoufei Saya menguji jawaban Anda dan berikut adalah versi terbarunya:

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"
  • Anda harus menggunakan dua %tanda di depan G dan H.
  • Ganti urutannya: pertama hapus semua file, lalu hapus semua direktori
  • (opsional :) Sebagai ganti %~1dapat digunakan nama direktori apa pun, saya menggunakan ini sebagai fungsi dalam file bat, jadi %~1parameter input pertama
Nikola
sumber
0

Jika Anda tidak ingin menulis kode apa pun, svn2.exe dari svn2svn melakukan ini, juga ada artikel tentang cara penerapannya. Folder dan file yang dihapus dimasukkan ke dalam recycle bin.

Jalankan "svn2.exe sync [path]".

dB.
sumber
0

Untuk orang-orang yang suka melakukan ini dengan perl, bukan python, Unix shell, java, dll. Dengan ini, skrip perl kecil yang juga melakukan jib.

Catatan: Ini juga menghapus semua direktori tidak berversi

#!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();
Craig McQueen
sumber
0

Cara bersih untuk melakukan ini di PERL adalah:

#!/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 ()
JT Marsh
sumber
0

Saya menggunakan ~ 3 jam untuk menghasilkan ini. Diperlukan waktu 5 menit untuk melakukannya di Unix. Masalah utama adalah: spasi dalam nama untuk folder Win, ketidakmungkinan untuk mengedit %% i dan masalah dengan mendefinisikan vars di loop cmd Win.

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!
)
Ilya Rosman
sumber
0

C # kode snipet di atas tidak bekerja untuk saya - Saya memiliki klien svn tortoise, dan baris diformat sedikit berbeda. Berikut adalah snipet kode yang sama seperti di atas, hanya ditulis ulang untuk berfungsi dan menggunakan 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
TarmoPikaro
sumber