最近TortoiseSVNが1.7になって、既存のワーキングコピーを初めて操作するときに自動的に管理ファイルをアップデートするらしい既存のワーキングコピーを手動でアップデートする必要があるらしい ( WC-NG )。未アップデートのワーキングコピーが混在するのは気持ち悪いのでまとめてアップデートしたいと思う。
しかし、僕の場合、ワーキングコピーがいろんなところに散在していて探すのがめんどくさい。それでワーキングコピーのルートフォルダをリストアップするコマンドラインアプリを作りました。
また、複数のプロジェクトをメンテしていてコミットがおろそかになってしまうことが多いんですが、これで列挙すればどこにワーキングセットがあるのか分かりやすくなります。
各ドライブ以下を全検索するのはやってられないので、Everythingの力を借りています。
そのためNTFSフォーマットのドライブ限定になります。
package require Tk
package require Ffidl
namespace eval Win32 {
variable HWND_DESKTOP 0
ffidl::callout GetDC {pointer} pointer [ffidl::symbol user32.dll GetDC]
ffidl::callout ReleaseDC {pointer pointer} int [ffidl::symbol user32.dll ReleaseDC]
}
namespace eval Gdi32 {
ffidl::callout GetPixel {pointer int int} int [ffidl::symbol gdi32.dll GetPixel]
ffidl::callout SetPixel {pointer int int int} int [ffidl::symbol gdi32.dll SetPixel]
}
proc GetPixel {hdc x y} {
set c [Gdi32::GetPixel $hdc $x $y]
set R [expr {($c & 0x000000FF)}]
set G [expr {($c & 0x0000FF00) >> 8}]
set B [expr {($c & 0x00FF0000) >> 16}]
return [list $R $G $B]
}
proc SetPixel {hdc x y r g b} {
set c [expr {(int($r & 0x00FF0000) >> 16)
| (int($g & 0x0000FF00))
| (int($b & 0x000000FF) << 16)
}]
Gdi32::SetPixel $hdc $x $y $c
}
# demo
set c [canvas .c]
pack $c
$c create text 55 95 -text "ABC" -fill white
$c create rect 125 25 145 45 -fill red
$c create oval 25 125 45 145 -fill green
$c create line 15 100 70 125 -fill blue
$c create poly 100 65 130 65 100 20 -fill cyan -outline black
bind $c <Motion> {
set x [winfo pointerx .]
set y [winfo pointery .]
set hdc [Win32::GetDC $::Win32::HWND_DESKTOP]
foreach {R G B} [GetPixel $hdc $x $y] break
Win32::ReleaseDC $::Win32::HWND_DESKTOP $hdc
wm title . "(x, y) = ($x, $y) : ($R, $G, $B)"
}
console show |
package require Tk
package require Ffidl
namespace eval Win32 {
variable HWND_DESKTOP 0
ffidl::callout GetDC {pointer} pointer [ffidl::symbol user32.dll GetDC]
ffidl::callout ReleaseDC {pointer pointer} int [ffidl::symbol user32.dll ReleaseDC]
}
namespace eval Gdi32 {
ffidl::callout GetPixel {pointer int int} int [ffidl::symbol gdi32.dll GetPixel]
ffidl::callout SetPixel {pointer int int int} int [ffidl::symbol gdi32.dll SetPixel]
}
proc GetPixel {hdc x y} {
set c [Gdi32::GetPixel $hdc $x $y]
set R [expr {($c & 0x000000FF)}]
set G [expr {($c & 0x0000FF00) >> 8}]
set B [expr {($c & 0x00FF0000) >> 16}]
return [list $R $G $B]
}
proc SetPixel {hdc x y r g b} {
set c [expr {(int($r & 0x00FF0000) >> 16)
| (int($g & 0x0000FF00))
| (int($b & 0x000000FF) << 16)
}]
Gdi32::SetPixel $hdc $x $y $c
}
# demo
set c [canvas .c]
pack $c
$c create text 55 95 -text "ABC" -fill white
$c create rect 125 25 145 45 -fill red
$c create oval 25 125 45 145 -fill green
$c create line 15 100 70 125 -fill blue
$c create poly 100 65 130 65 100 20 -fill cyan -outline black
bind $c <Motion> {
set x [winfo pointerx .]
set y [winfo pointery .]
set hdc [Win32::GetDC $::Win32::HWND_DESKTOP]
foreach {R G B} [GetPixel $hdc $x $y] break
Win32::ReleaseDC $::Win32::HWND_DESKTOP $hdc
wm title . "(x, y) = ($x, $y) : ($R, $G, $B)"
}
console show
ここからes.exeをダウンロードして、スクリプトの実行フォルダかパスの通ったフォルダに置く必要があります。
http://www.voidtools.com/download.php
※ Tclインタープリタ不要なバージョンも作りました。
これにもes.exeは必要です。
FindSvnRoots 1.0.0.0 (Windows binary)
# 未コミットかどうかも表示できるようにしたい。
2011-10-27 追記
svn status -qコマンドで取得した状態で、" "でないものがあった場合は最初に見つけたものを表示します。
>FindSvnRoots.exe
C:\src\my\project1
M C:\src\my\project2
A C:\src\my\project2 |
>FindSvnRoots.exe
C:\src\my\project1
M C:\src\my\project2
A C:\src\my\project2
svnコマンドにパスが通っていない場合は全ての状態が" "になります。
>FindSvnRoots.exe
C:\src\my\project1
C:\src\my\project2 |
>FindSvnRoots.exe
C:\src\my\project1
C:\src\my\project2
FindSvnRoots 2.0.0.0 (Windows binary)
ソースコードは以下。
# This script searches all subversion working copy root folders.
# You need Everything command line interface (es.exe).
# tclsh FindSvnRoots.tcl
# Output format:
# [ ACDIMRX?!~] "Working set folder's full path"
set svn_exists [expr {![catch {exec svn --version --quiet}]}]
array set wcopy {}
set ch [open {|es -i -s -r "^.svn$"}]
while {![eof $ch]} {
if {[gets $ch path] != -1} {
set parent [file dirname $path]
set wcopy($parent) 1
}
}
set paths [lsort -dictionary [array names wcopy]]
foreach path $paths {
array unset wcopy "${path}?*"
}
set paths [lsort -dictionary [array names wcopy]]
foreach path $paths {
set native_path [file nativename $path]
set s " "
if {$svn_exists} {
if {[catch {exec svn status -q $path} str]} {
puts "E $path : Failed to retrieve local modification : [lindex [split $str \n] 0]"
}
set lines [split $str \n]
foreach line $lines {
set s [string index $line 0]
if {$s ne " "} {
break
}
}
}
puts "$s $native_path"
} |
# This script searches all subversion working copy root folders.
# You need Everything command line interface (es.exe).
# tclsh FindSvnRoots.tcl
# Output format:
# [ ACDIMRX?!~] "Working set folder's full path"
set svn_exists [expr {![catch {exec svn --version --quiet}]}]
array set wcopy {}
set ch [open {|es -i -s -r "^.svn$"}]
while {![eof $ch]} {
if {[gets $ch path] != -1} {
set parent [file dirname $path]
set wcopy($parent) 1
}
}
set paths [lsort -dictionary [array names wcopy]]
foreach path $paths {
array unset wcopy "${path}?*"
}
set paths [lsort -dictionary [array names wcopy]]
foreach path $paths {
set native_path [file nativename $path]
set s " "
if {$svn_exists} {
if {[catch {exec svn status -q $path} str]} {
puts "E $path : Failed to retrieve local modification : [lindex [split $str \n] 0]"
}
set lines [split $str \n]
foreach line $lines {
set s [string index $line 0]
if {$s ne " "} {
break
}
}
}
puts "$s $native_path"
}