📄 svn.tcl
字号:
# Find SVN URL
proc read_svn_dir {dirname} {
global cvscfg
global cvsglb
global current_tagname
global module_dir
global cmd
gen_log:log T "ENTER ($dirname)"
# svn info gets the URL
set cmd(info) [exec::new "svn info"]
set info_lines [$cmd(info)\::output]
foreach infoline [split $info_lines "\n"] {
if {[string match "URL:*" $infoline]} {
#gen_log:log D "$infoline"
set cvscfg(url) [lrange $infoline 1 end]
}
}
if {$cvscfg(url) == ""} {
cvsfail "Can't get the SVN URL"
return
}
foreach s {trunk branches tags} {
if {[regexp "/$s/" $cvscfg(url)] || [regexp "/$s" $cvscfg(url)]} {
set spl [split $cvscfg(url) "/"]
set root ""
set relp ""
set current_tagname ""
set state P
for {set j 0} {$j < [llength $spl]} {incr j} {
set word [lindex $spl $j]
switch -- $state {
P {
switch -- $word {
"trunk" {
set type $word
set current_tagname $word
set state E
}
"branches" {
set type $word
set state W
}
"tags" {
set type $word
set state W
}
default { append root "$word/" }
}
}
W {
set current_tagname $word
set state E
}
E {
lappend relp "$word"
}
default {}
}
}
set cvscfg(svnroot) [string trimright $root "/"]
gen_log:log D "SVN URL: $cvscfg(url)"
gen_log:log D "svnroot: $cvscfg(svnroot)"
set cvsglb(relpath) [join $relp {/}]
gen_log:log D "relpath: $cvsglb(relpath)"
regsub -all {%20} $cvsglb(relpath) { } module_dir
gen_log:log D "tagname: $current_tagname"
}
}
gen_log:log T "LEAVE"
}
# Get stuff for main workdir browser
proc svn_workdir_status {} {
global cmd
global Filelist
gen_log:log T "ENTER"
set cmd(svn_status) [exec::new "svn status -uvN"]
set status_lines [split [$cmd(svn_status)\::output] "\n"]
catch {unset cmd(svn_status)}
# The first five columns in the output are each one character wide
foreach logline $status_lines {
if {[string match "Status*" $logline]} {continue}
if {[string length $logline] < 1} {continue}
set cauthor ""
set crev ""
set wrev ""
set status ""
set varcols [string range $logline 8 end]
if {[llength $varcols] > 1} {
#012345678
# M 965 938 kfogel wc/bar.c
# * 965 922 sussman wc/foo.c
#A + 965 687 joe wc/qax.c
# 965 687 joe wc/zig.c
set wrev [lindex $varcols 0]
set crev [lindex $varcols 1]
set cauthor [lindex $varcols 2]
set filename [lrange $varcols 3 end]
} else {
#? newfile
set filename [lrange $logline 1 end]
}
set modstat [string range $logline 0 7]
set m1 [string index $modstat 0]
set displaymod ""
if [file isdirectory $filename] {
set displaymod "<dir> "
}
switch -exact -- $m1 {
" " { append displaymod "Up-to-date" }
M { append displaymod "Locally Modified" }
A { append displaymod "Locally Added" }
D { append displaymod "Locally Removed" }
? { append displaymod "Not managed by SVN" }
C { append displaymod "Conflict" }
L { append displaymod "Locked" }
S { append displaymod "Switched to Branch" }
! { append displaymod "Missing or Incomplete" }
~ { append displaymod "Dir/File Mismatch" }
}
if {[string index $modstat 7] == "*"} {
set displaymod "Out-of-date"
}
set Filelist($filename:wrev) $wrev
set Filelist($filename:status) $displaymod
set Filelist($filename:stickytag) "$wrev $crev"
if {$wrev != "" && $crev != ""} {
#set Filelist($filename:stickytag) "working:$wrev committed:$crev"
set Filelist($filename:stickytag) "$wrev (committed:$crev)"
}
set Filelist($filename:option) ""
set Filelist($filename:editors) "$cauthor"
}
gen_log:log T "LEAVE"
}
# does svn add from workdir browser
proc svn_add {args} {
global cvscfg
gen_log:log T "ENTER ($args)"
set filelist [join $args]
if {$filelist == ""} {
set mess "This will add all new files"
} else {
set mess "This will add these files:\n\n"
foreach file $filelist {
append mess " $file\n"
}
}
if {$filelist == ""} {
append filelist [glob -nocomplain $cvscfg(aster) .??*]
}
set cmd(svnadd) [exec::new "svn add $filelist"]
if {$cvscfg(auto_status)} {
$cmd(svnadd)\::wait
setup_dir
}
gen_log:log T "LEAVE"
}
# does svn remove from workdir browser
proc svn_remove {args} {
global cvscfg
global cmd
gen_log:log T "ENTER ($args)"
set filelist [join $args]
set cmd(svndel) [exec::new "svn remove $filelist"]
if {$cvscfg(auto_status)} {
$cmd(svndel)\::wait
setup_dir
}
gen_log:log T "LEAVE"
}
# called from the workdir browser checkmark button
proc svn_check {directory {v {0}} } {
global cvscfg
gen_log:log T "ENTER ($directory $v)"
busy_start .workdir.main
set flags ""
if {$v} {
append flags "uv"
}
if {! $cvscfg(recurse)} {
append flags "N"
}
if {$flags != ""} {
set flags "-$flags"
}
set command "svn status $flags $directory"
set check_cmd [viewer::new "SVN Status Check"]
$check_cmd\::do "$command" 0 status_colortags
busy_done .workdir.main
gen_log:log T "LEAVE"
}
# svn update - called from workdir browser
proc svn_update {args} {
global cvscfg
gen_log:log T "ENTER ($args)"
set filelist [join $args]
if {$filelist == ""} {
append mess "\nThis will download from"
append mess " the repository to your local"
append mess " filespace ** ALL ** files which"
append mess " have changed in it."
} else {
append mess "\nThis will download from"
append mess " the repository to your local"
append mess " filespace these files which"
append mess " have changed:\n"
}
foreach file $filelist {
append mess "\n\t$file"
}
append mess "\n\nAre you sure?"
set command "svn update"
if {[cvsconfirm $mess .workdir] == "ok"} {
foreach file $filelist {
append command " \"$file\""
}
} else {
return;
}
set co_cmd [viewer::new "SVN Update"]
$co_cmd\::do "$command" 0 status_colortags
if {$cvscfg(auto_status)} {
$co_cmd\::wait
setup_dir
}
gen_log:log T "LEAVE"
}
# Called from "update with options" dialog of workdir browser
proc svn_opt_update {} {
global cvscfg
global cvsglb
switch -exact -- $cvsglb(tagmode_selection) {
"Keep" {
set command "svn update"
}
"Trunk" {
set command "svn switch $cvscfg(svnroot)/trunk"
}
"Branch" {
set command "svn switch $cvscfg(svnroot)/branches/$cvsglb(branchname)"
}
"Revision" {
# Let them get away with saying r3 instead of 3
set rev [string trimleft $cvsglb(revnumber) {r}]
set command "svn update -r $rev"
}
}
set upd_cmd [viewer::new "SVN Update/Switch"]
$upd_cmd\::do "$command" 0 status_colortags
if {$cvscfg(auto_status)} {
$upd_cmd\::wait
setup_dir
}
}
# dialog for svn commit - called from workdir browser
proc svn_commit_dialog {} {
global cvsglb
global cvscfg
# If marked files, commit these. If no marked files, then
# commit any files selected via listbox selection mechanism.
# The cvsglb(commit_list) list remembers the list of files
# to be committed.
set cvsglb(commit_list) [workdir_list_files]
# If we want to use an external editor, just do it
if {$cvscfg(use_cvseditor)} {
svn_commit "" "" $cvsglb(commit_list)
return
}
if {[winfo exists .commit]} {
destroy .commit
}
toplevel .commit
grab set .commit
frame .commit.top -border 8
frame .commit.down -relief groove -border 2
pack .commit.top -side top -fill x
pack .commit.down -side bottom -fill x
frame .commit.comment
pack .commit.comment -side top -fill both -expand 1
label .commit.lcomment
text .commit.tcomment -relief sunken -width 70 -height 10 \
-bg $cvsglb(textbg) -exportselection 1 \
-wrap word -border 2 -setgrid yes
# Explain what it means to "commit" files
message .commit.message -justify left -aspect 800 \
-text "This will commit changes from your \
local, working directory into the repository, recursively."
pack .commit.message -in .commit.top -padx 2 -pady 5
button .commit.ok -text "OK" \
-command {
grab release .commit
wm withdraw .commit
set cvsglb(commit_comment) [.commit.tcomment get 1.0 end]
svn_commit $cvsglb(commit_comment) $cvsglb(commit_list)
}
button .commit.apply -text "Apply" \
-command {
set cvsglb(commit_comment) [.commit.tcomment get 1.0 end]
svn_commit $cvsglb(commit_comment) $cvsglb(commit_list)
}
button .commit.clear -text "ClearAll" \
-command {
set version ""
.commit.tcomment delete 1.0 end
}
button .commit.quit \
-command {
grab release .commit
wm withdraw .commit
}
.commit.lcomment configure -text "Your log message" \
-anchor w
.commit.ok configure -text "OK"
.commit.quit configure -text "Close"
pack .commit.lcomment -in .commit.comment \
-side left -fill x -pady 3
pack .commit.tcomment -in .commit.comment \
-side left -fill both -expand 1 -pady 3
pack .commit.ok .commit.apply .commit.clear .commit.quit -in .commit.down \
-side left -ipadx 2 -ipady 2 -padx 4 -pady 4 -fill both -expand 1
# Fill in the most recent commit message
.commit.tcomment insert end $cvsglb(commit_comment)
wm title .commit "Commit Changes"
wm minsize .commit 1 1
gen_log:log T "LEAVE"
}
# svn commit - called from commit dialog
proc svn_commit {comment args} {
global cvscfg
gen_log:log T "ENTER ($comment $args)"
set filelist [join $args]
set commit_output ""
if {$filelist == ""} {
set mess "This will commit your changes to ** ALL ** files in"
append mess " and under this directory."
} else {
foreach file $filelist {
append commit_output "\n$file"
}
set mess "This will commit your changes to:$commit_output"
}
append mess "\n\nAre you sure?"
set commit_output ""
if {[cvsconfirm $mess .workdir] != "ok"} {
return 1
}
if {$cvscfg(use_cvseditor)} {
# Starts text editor of your choice to enter the log message.
update idletasks
set command \
"$cvscfg(terminal) svn commit $filelist"
gen_log:log C "$command"
set ret [catch {eval "exec $command"} view_this]
if {$ret} {
cvsfail $view_this .workdir
gen_log:log T "LEAVE ERROR ($view_this)"
return
}
} else {
if {$comment == ""} {
cvsfail "You must enter a comment!" .commit
return 1
}
set v [viewer::new "SVN Commit"]
regsub -all "\"" $comment "\\\"" comment
$v\::do "svn commit -m \"$comment\" $filelist" 1
$v\::wait
}
if {$cvscfg(auto_status)} {
setup_dir
}
gen_log:log T "LEAVE"
}
# Called from workdir browser annotate button
proc svn_annotate {revision args} {
global cvscfg
gen_log:log T "ENTER ($revision $args)"
if {$revision != ""} {
# We were given a revision
set revflag "-r$revision"
} else {
set revflag ""
}
set filelist [join $args]
if {$filelist == ""} {
cvsfail "Annotate:\nPlease select one or more files !" .workdir
gen_log:log T "LEAVE (Unselected files)"
return
}
foreach file $filelist {
annotate::new $revflag $file "svn"
}
gen_log:log T "LEAVE"
}
# Called from branch browser annotate button
proc svn_annotate_r {revision filepath} {
global cvscfg
gen_log:log T "ENTER ($revision $filepath)"
set revflag "-r$revision"
annotate::new $revflag $filepath "svn_r"
gen_log:log T "LEAVE"
}
proc svn_patch { pathA pathB revA dateA revB dateB outmode outfile } {
#
# This creates a patch file between two revisions of a module. If the
# second revision is null, it creates a patch to the head revision.
# If both are null the top two revisions of the file are diffed.
#
global cvscfg
gen_log:log T "ENTER ($pathA $pathB $revA $dateA $revB $dateB $outmode $outfile)"
global cvs
foreach {rev1 rev2} {{} {}} { break }
if {$revA != {}} {
set rev1 $revA
} elseif {$dateA != {}} {
set rev1 "\{\"$dateA\"\}"
}
if {$revB != {}} {
set rev2 "$revB"
} elseif {$dateA != {}} {
set rev2 "\{\"$dateB\"\}"
}
set pathA [safe_url $pathA]
set pathB [safe_url $pathB]
if {$pathA != {} && $pathB != {}} {
set command "svn diff $pathA $pathB"
} elseif {$rev1 != {} && $rev2 != {}} {
set command "svn diff $pathA@$rev1 $pathA@$rev2"
} else {
cvsfail "Specify either two paths OR one path and two revisions"
return
}
if {$outmode == 0} {
set v [viewer::new "SVN Diff"]
$v\::do "$command"
} else {
set e [exec::new "$command"]
set patch [$e\::output]
gen_log:log F "OPEN $outfile"
if {[catch {set fo [open $outfile w]}]} {
cvsfail "Cannot open $outfile for writing" .modbrowse
return
}
puts $fo $patch
close $fo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -