1# 2# Tcl Library for TkCVS 3# 4 5# 6# Current working directory display. Handles all of the functions 7# concerned with navigating about the current directory on the main 8# window. 9# 10 11proc workdir_setup {} { 12 global cwd 13 global module_dir 14 global cvscfg 15 global cvsglb 16 global current_tagname 17 global logclass 18 global tcl_platform 19 20 gen_log:log T "ENTER" 21 set cwd [pwd] 22 set pid [pid] 23 24 if {[winfo exists .workdir]} { 25 wm deiconify .workdir 26 raise .workdir 27 return 28 } 29 30 # Make a new toplevel and unmap . so that the working directory browser 31 # the module browser are equal 32 toplevel .workdir 33 wm title .workdir "TkCVS $cvscfg(version) Working Directory" 34 wm iconname .workdir "TkCVS" 35 if {$tcl_platform(platform) eq "unix"} { 36 wm iconbitmap .workdir @$cvscfg(bitmapdir)/tkcvs48.xbm 37 } 38 wm minsize .workdir 430 300 39 wm protocol .workdir WM_DELETE_WINDOW { .workdir.close invoke } 40 wm withdraw . 41 42 if {[catch "image type Conflict"]} { 43 workdir_images 44 } 45 if {[info exists cvscfg(workgeom)]} { 46 wm geometry .workdir $cvscfg(workgeom) 47 } 48 49 workdir_menus 50 51 # 52 # Top section - where we are, where the module is 53 # 54 frame .workdir.top -relief groove -border 2 55 pack .workdir.top -side top -fill x 56 57 ::picklist::entry .workdir.top.tcwd cwd directory 58 ::picklist::bind .workdir.top.tcwd <Return> \ 59 {if {[pwd] != $cwd} {change_dir "$cwd"}} 60 61 button .workdir.top.updir_btn -image updir \ 62 -command {change_dir ..} 63 64 label .workdir.top.lmodule -text "Path" 65 label .workdir.top.tmodule -textvariable module_dir -anchor w -relief groove 66 67 label .workdir.top.ltagname -text "Tag" 68 label .workdir.top.ttagname -textvariable current_tagname \ 69 -anchor w -relief groove 70 71 # Make the Repository Browser button prominent 72 button .workdir.top.bmodbrowse -image Modules \ 73 -command modbrowse_run 74 75 label .workdir.top.lcvsroot -text "CVSROOT" 76 entry .workdir.top.tcvsroot -textvariable cvscfg(cvsroot) \ 77 -bd 1 -relief sunk -state readonly 78 79 grid columnconf .workdir.top 1 -weight 1 80 grid rowconf .workdir.top 3 -weight 1 81 grid .workdir.top.updir_btn -column 0 -row 0 -sticky s 82 grid .workdir.top.tcwd -column 1 -row 0 -columnspan 2 \ 83 -sticky sew -padx 4 -pady 1 84 grid .workdir.top.lmodule -column 0 -row 1 -sticky nw 85 grid .workdir.top.tmodule -column 1 -row 1 -columnspan 2\ 86 -padx 4 -pady 1 -sticky new 87 grid .workdir.top.bmodbrowse -column 2 -row 2 -rowspan 2 -sticky w 88 grid .workdir.top.ltagname -column 0 -row 2 -sticky nw 89 grid .workdir.top.ttagname -column 1 -row 2 -padx 4 -pady 1 -sticky new 90 grid .workdir.top.lcvsroot -column 0 -row 3 -sticky nw 91 grid .workdir.top.tcvsroot -column 1 -row 3 -padx 3 -sticky new 92 93 94 # Pack the bottom before the middle so it doesnt disappear if 95 # the window is resized smaller 96 #frame .workdir.bottom -relief groove -border 2 -height 128 97 frame .workdir.bottom 98 frame .workdir.bottom.filters -relief raised 99 pack .workdir.bottom -side bottom -fill x 100 pack .workdir.bottom.filters -side top -fill x 101 102 label .workdir.bottom.filters.showlbl -text "Show:" -anchor w 103 entry .workdir.bottom.filters.showentry -textvariable cvscfg(file_filter) -width 12 104 label .workdir.bottom.filters.hidelbl -text " Hide:" -anchor w 105 entry .workdir.bottom.filters.hideentry -width 12 \ 106 -textvariable cvsglb(default_ignore_filter) 107 label .workdir.bottom.filters.space -text " " 108 button .workdir.bottom.filters.cleanbutton -text "Clean:" \ 109 -pady 0 -highlightthickness 0 \ 110 -command workdir_cleanup 111 entry .workdir.bottom.filters.cleanentry -width 12 \ 112 -textvariable cvscfg(clean_these) 113 bind .workdir.bottom.filters.showentry <Return> {setup_dir} 114 bind .workdir.bottom.filters.hideentry <Return> { 115 set cvsglb(default_ignore_filter) [.workdir.bottom.filters.hideentry get] 116 setup_dir} 117 bind .workdir.bottom.filters.cleanentry <Return> {workdir_cleanup} 118 pack .workdir.bottom.filters.showlbl -side left 119 pack .workdir.bottom.filters.showentry -side left 120 pack .workdir.bottom.filters.hidelbl -side left 121 pack .workdir.bottom.filters.hideentry -side left 122 pack .workdir.bottom.filters.space -side left 123 pack .workdir.bottom.filters.cleanbutton -side left -ipadx 2 -ipady 0 124 pack .workdir.bottom.filters.cleanentry -side left 125 126 frame .workdir.bottom.buttons -relief groove -bd 2 127 frame .workdir.bottom.buttons.funcs -relief groove -bd 2 128 frame .workdir.bottom.buttons.dirfuncs -relief groove -bd 2 129 frame .workdir.bottom.buttons.cvsfuncs -relief groove -bd 2 130 frame .workdir.bottom.buttons.oddfuncs -relief groove -bd 2 131 frame .workdir.bottom.buttons.close -relief groove -bd 2 132 pack .workdir.bottom.buttons -side top -fill x -expand yes 133 pack .workdir.bottom.buttons.close -side right -padx 10 134 pack .workdir.bottom.buttons.funcs -side left -expand yes -anchor w 135 pack .workdir.bottom.buttons.dirfuncs -side left -expand yes -anchor w 136 pack .workdir.bottom.buttons.cvsfuncs -side left -expand yes -anchor w 137 pack .workdir.bottom.buttons.oddfuncs -side left -expand yes -anchor w 138 139 # 140 # Action buttons along the bottom of the screen. 141 # 142 button .workdir.bottom.buttons.funcs.bedit_files -image Fileedit \ 143 -command { workdir_edit_file [workdir_list_files] } 144 button .workdir.bottom.buttons.funcs.bview_files -image Fileview \ 145 -command { workdir_view_file [workdir_list_files] } 146 button .workdir.bottom.buttons.funcs.bdelete_file -image Delete \ 147 -command { workdir_delete_file [workdir_list_files] } 148 button .workdir.bottom.buttons.funcs.bmkdir -image Dir_new \ 149 -command { file_input_and_do "New Directory" workdir_newdir} 150 151 button .workdir.bottom.buttons.dirfuncs.brefresh -image Refresh \ 152 -command { setup_dir } 153 button .workdir.bottom.buttons.dirfuncs.bcheckdir -image Check 154 155 button .workdir.bottom.buttons.cvsfuncs.blogfile -image Branches \ 156 -command { cvs_branches [workdir_list_files] } 157 button .workdir.bottom.buttons.cvsfuncs.bannotate -image Annotate \ 158 -command { cvs_annotate $current_tagname [workdir_list_files] } 159 button .workdir.bottom.buttons.cvsfuncs.bfilelog -image Log \ 160 -command { cvs_log [workdir_list_files] } 161 button .workdir.bottom.buttons.cvsfuncs.bdiff -image Diff \ 162 -command { comparediff [workdir_list_files] } 163 button .workdir.bottom.buttons.cvsfuncs.bconflict -image Conflict \ 164 -command { cvs_merge_conflict [workdir_list_files] } 165 166 button .workdir.bottom.buttons.cvsfuncs.btag -image Tag \ 167 -command { file_tag_dialog "tag" } 168 button .workdir.bottom.buttons.cvsfuncs.bbranchtag -image Branchtag \ 169 -command { file_tag_dialog "branch" } 170 button .workdir.bottom.buttons.cvsfuncs.badd_files -image Add \ 171 -command { add_dialog [workdir_list_files] } 172 button .workdir.bottom.buttons.cvsfuncs.bremove -image Remove \ 173 -command { subtract_dialog [workdir_list_files] } 174 button .workdir.bottom.buttons.cvsfuncs.bcheckin -image Checkin \ 175 -command cvs_commit_dialog 176 button .workdir.bottom.buttons.cvsfuncs.bupdate -image Checkout 177 button .workdir.bottom.buttons.cvsfuncs.bupdateopts -image CheckoutOpts \ 178 -command { cvs_update_options } 179 button .workdir.bottom.buttons.cvsfuncs.brevert -image Revert \ 180 -command { cvs_revert [workdir_list_files] } 181 button .workdir.bottom.buttons.cvsfuncs.bjoin -image DirBranches \ 182 -command cvs_joincanvas 183 184 button .workdir.bottom.buttons.oddfuncs.bcvsedit_files -image Edit \ 185 -command { cvs_edit [workdir_list_files] } 186 button .workdir.bottom.buttons.oddfuncs.bunedit_files -image Unedit \ 187 -command { cvs_unedit [workdir_list_files] } 188 button .workdir.bottom.buttons.oddfuncs.block -image Lock 189 button .workdir.bottom.buttons.oddfuncs.bunlock -image UnLock 190 button .workdir.close -text "Close" \ 191 -command { 192 global cvscfg 193 set cvscfg(workgeom) [wm geometry .workdir] 194 destroy .workdir 195 exit_cleanup 0 196 } 197 198 # These buttons work in any directory 199 grid .workdir.bottom.buttons.funcs.bdelete_file -column 0 -row 0 \ 200 -ipadx 4 201 grid .workdir.bottom.buttons.funcs.bedit_files -column 1 -row 0 \ 202 -ipadx 4 203 grid .workdir.bottom.buttons.funcs.bmkdir -column 0 -row 1 \ 204 -ipadx 4 205 grid .workdir.bottom.buttons.funcs.bview_files -column 1 -row 1 \ 206 -ipadx 4 207 208 # Directory functions 209 grid rowconf .workdir.bottom.buttons.dirfuncs 0 -weight 1 210 grid .workdir.bottom.buttons.dirfuncs.brefresh -column 0 -row 0 \ 211 -ipadx 4 -ipady 4 212 grid .workdir.bottom.buttons.dirfuncs.bcheckdir -column 1 -row 0 \ 213 -ipadx 4 -ipady 4 214 215 # Revcontrol functions 216 grid .workdir.bottom.buttons.cvsfuncs.blogfile -column 0 -row 0 \ 217 -ipadx 4 218 grid .workdir.bottom.buttons.cvsfuncs.bjoin -column 0 -row 1 \ 219 -ipadx 4 220 grid .workdir.bottom.buttons.cvsfuncs.bdiff -column 1 -row 0 \ 221 -ipadx 2 222 grid .workdir.bottom.buttons.cvsfuncs.bconflict -column 1 -row 1 \ 223 -ipadx 2 224 grid .workdir.bottom.buttons.cvsfuncs.bfilelog -column 2 -row 0 225 grid .workdir.bottom.buttons.cvsfuncs.bannotate -column 2 -row 1 226 grid .workdir.bottom.buttons.cvsfuncs.bupdate -column 3 -row 0 \ 227 -ipadx 4 228 grid .workdir.bottom.buttons.cvsfuncs.bcheckin -column 3 -row 1 \ 229 -ipadx 4 230 grid .workdir.bottom.buttons.cvsfuncs.bupdateopts -column 4 -row 0 \ 231 -ipadx 4 232 grid .workdir.bottom.buttons.cvsfuncs.brevert -column 4 -row 1 \ 233 -ipadx 4 234 grid .workdir.bottom.buttons.cvsfuncs.badd_files -column 5 -row 0 235 grid .workdir.bottom.buttons.cvsfuncs.bremove -column 5 -row 1 236 grid .workdir.bottom.buttons.cvsfuncs.btag -column 6 -row 0 \ 237 -ipadx 4 238 grid .workdir.bottom.buttons.cvsfuncs.bbranchtag -column 6 -row 1 \ 239 -ipadx 4 240 241 # These are specialized an not always available 242 grid .workdir.bottom.buttons.oddfuncs.block -column 0 -row 0 243 grid .workdir.bottom.buttons.oddfuncs.bunlock -column 0 -row 1 244 grid .workdir.bottom.buttons.oddfuncs.bcvsedit_files -column 1 -row 0 245 grid .workdir.bottom.buttons.oddfuncs.bunedit_files -column 1 -row 1 246 247 pack .workdir.close -in .workdir.bottom.buttons.close \ 248 -side right -fill both -expand yes 249 250 set_tooltips .workdir.top.updir_btn \ 251 {"Go up (..)"} 252 set_tooltips .workdir.bottom.buttons.funcs.bedit_files \ 253 {"Edit the selected files"} 254 set_tooltips .workdir.bottom.buttons.funcs.bview_files \ 255 {"View the selected files"} 256 set_tooltips .workdir.bottom.buttons.funcs.bdelete_file \ 257 {"Delete the selected files from the current directory"} 258 set_tooltips .workdir.bottom.buttons.funcs.bmkdir \ 259 {"Make a new directory"} 260 261 set_tooltips .workdir.bottom.buttons.dirfuncs.brefresh \ 262 {"Re-read the current directory"} 263 set_tooltips .workdir.bottom.buttons.cvsfuncs.bjoin \ 264 {"Directory Branch Diagram and Merge Tool"} 265 set_tooltips .workdir.bottom.buttons.dirfuncs.bcheckdir \ 266 {"Check the status of the directory"} 267 268 set_tooltips .workdir.bottom.buttons.cvsfuncs.blogfile \ 269 {"Graphical Branch Diagram of the selected files"} 270 set_tooltips .workdir.bottom.buttons.cvsfuncs.bfilelog \ 271 {"Revision Log of the selected files"} 272 set_tooltips .workdir.bottom.buttons.cvsfuncs.bannotate \ 273 {"Revision where each line was modified (annotate/blame)"} 274 set_tooltips .workdir.bottom.buttons.cvsfuncs.bdiff \ 275 {"Compare the selected files with the repository version"} 276 set_tooltips .workdir.bottom.buttons.cvsfuncs.bconflict \ 277 {"Merge Conflicts using TkDiff"} 278 set_tooltips .workdir.bottom.buttons.cvsfuncs.badd_files \ 279 {"Add the selected files to the repository"} 280 set_tooltips .workdir.bottom.buttons.cvsfuncs.btag \ 281 {"Tag the selected files"} 282 set_tooltips .workdir.bottom.buttons.cvsfuncs.bbranchtag \ 283 {"Branch the selected files"} 284 set_tooltips .workdir.bottom.buttons.cvsfuncs.bremove \ 285 {"Remove the selected files from the repository"} 286 set_tooltips .workdir.bottom.buttons.cvsfuncs.bcheckin \ 287 {"Check in (commit) the selected files to the repository"} 288 set_tooltips .workdir.bottom.buttons.cvsfuncs.bupdate \ 289 {"Update (checkout, patch) the selected files from the repository"} 290 set_tooltips .workdir.bottom.buttons.cvsfuncs.brevert \ 291 {"Revert the selected files, discarding local edits"} 292 set_tooltips .workdir.bottom.buttons.cvsfuncs.bupdateopts \ 293 {"Update with options (-A, -r, -f, -d, -kb)"} 294 295 set_tooltips .workdir.bottom.buttons.oddfuncs.block \ 296 {"Lock the selected files"} 297 set_tooltips .workdir.bottom.buttons.oddfuncs.bunlock \ 298 {"Unlock the selected files"} 299 set_tooltips .workdir.bottom.buttons.oddfuncs.bcvsedit_files \ 300 {"Set the Edit flag on the selected files"} 301 set_tooltips .workdir.bottom.buttons.oddfuncs.bunedit_files \ 302 {"Reset the Edit flag on the selected files"} 303 304 set_tooltips .workdir.top.bmodbrowse \ 305 {"Open the Repository Browser"} 306 set_tooltips .workdir.close \ 307 {"Close the Working Directory Browser"} 308 309 310 frame .workdir.main 311 pack .workdir.main -side bottom -fill both -expand 1 -fill both 312 update idletasks 313 314 if {! [winfo ismapped .workdir]} { 315 wm deiconify .workdir 316 } 317 318 #change_dir "[pwd]" 319 setup_dir 320 gen_log:log T "LEAVE" 321} 322 323proc workdir_images {} { 324 global cvscfg 325 326 image create photo arr_up \ 327 -format gif -file [file join $cvscfg(bitmapdir) arrow_up.gif] 328 image create photo arr_dn \ 329 -format gif -file [file join $cvscfg(bitmapdir) arrow_dn.gif] 330 image create photo arh_up \ 331 -format gif -file [file join $cvscfg(bitmapdir) arrow_hl_up.gif] 332 image create photo arh_dn \ 333 -format gif -file [file join $cvscfg(bitmapdir) arrow_hl_dn.gif] 334 image create photo updir \ 335 -format gif -file [file join $cvscfg(bitmapdir) updir.gif] 336 image create photo Folder \ 337 -format gif -file [file join $cvscfg(bitmapdir) dir.gif] 338 image create photo Check \ 339 -format gif -file [file join $cvscfg(bitmapdir) check.gif] 340 image create photo Fileview \ 341 -format gif -file [file join $cvscfg(bitmapdir) fileview.gif] 342 image create photo Fileedit \ 343 -format gif -file [file join $cvscfg(bitmapdir) fileedit.gif] 344 image create photo Annotate \ 345 -format gif -file [file join $cvscfg(bitmapdir) annotate.gif] 346 image create photo Delete \ 347 -format gif -file [file join $cvscfg(bitmapdir) delete.gif] 348 image create photo Dir_new \ 349 -format gif -file [file join $cvscfg(bitmapdir) dir_new.gif] 350 image create photo Refresh \ 351 -format gif -file [file join $cvscfg(bitmapdir) loop-glasses.gif] 352 image create photo Branches \ 353 -format gif -file [file join $cvscfg(bitmapdir) branch.gif] 354 image create photo DirBranches \ 355 -format gif -file [file join $cvscfg(bitmapdir) dirbranch.gif] 356 image create photo Add \ 357 -format gif -file [file join $cvscfg(bitmapdir) add.gif] 358 image create photo Remove \ 359 -format gif -file [file join $cvscfg(bitmapdir) remove.gif] 360 image create photo Diff \ 361 -format gif -file [file join $cvscfg(bitmapdir) diff.gif] 362 image create photo Checkin \ 363 -format gif -file [file join $cvscfg(bitmapdir) checkin.gif] 364 image create photo Revert \ 365 -format gif -file [file join $cvscfg(bitmapdir) loop-ball.gif] 366 image create photo Edit \ 367 -format gif -file [file join $cvscfg(bitmapdir) edit.gif] 368 image create photo Unedit \ 369 -format gif -file [file join $cvscfg(bitmapdir) unedit.gif] 370 image create photo Modules \ 371 -format gif -file [file join $cvscfg(bitmapdir) modbrowse.gif] 372 image create photo Modules_cvs \ 373 -format gif -file [file join $cvscfg(bitmapdir) modbrowse_cvs.gif] 374 image create photo Modules_svn \ 375 -format gif -file [file join $cvscfg(bitmapdir) modbrowse_svn.gif] 376 image create photo Lock \ 377 -format gif -file [file join $cvscfg(bitmapdir) locked.gif] 378 image create photo UnLock \ 379 -format gif -file [file join $cvscfg(bitmapdir) unlocked.gif] 380 image create photo Tags \ 381 -format gif -file [file join $cvscfg(bitmapdir) tags.gif] 382 image create photo Mergebranch \ 383 -format gif -file [file join $cvscfg(bitmapdir) newmerge_simple.gif] 384 image create photo Mergediff \ 385 -format gif -file [file join $cvscfg(bitmapdir) newmerge.gif] 386 image create photo Conflict \ 387 -format gif -file [file join $cvscfg(bitmapdir) conflict.gif] 388 389 image create photo Man \ 390 -format gif -file [file join $cvscfg(bitmapdir) man.gif] 391} 392 393proc workdir_menus {} { 394 global cvscfg 395 global cvsglb 396 global cvsmenu 397 global usermenu 398 global execmenu 399 global bookmarks 400 401 gen_log:log T "ENTER" 402 set startdir "[pwd]" 403 404 .workdir configure -menu .workdir.menubar 405 menu .workdir.menubar 406 407 # 408 # Create the Menu bar 409 # 410 .workdir.menubar add cascade -label "File" -menu .workdir.menubar.file -underline 0 411 menu .workdir.menubar.file -tearoff 0 412 .workdir.menubar add cascade -label "CVS" -menu .workdir.menubar.cvs -underline 0 413 menu .workdir.menubar.cvs -tearoff 0 414 .workdir.menubar add cascade -label "SVN" -menu .workdir.menubar.svn -underline 0 415 menu .workdir.menubar.svn -tearoff 0 416 .workdir.menubar add cascade -label "RCS" -menu .workdir.menubar.rcs -underline 0 417 menu .workdir.menubar.rcs -tearoff 0 418 .workdir.menubar add cascade -label "Reports" -menu .workdir.menubar.reports -underline 2 419 menu .workdir.menubar.reports -tearoff 0 420 .workdir.menubar add cascade -label "Options" -menu .workdir.menubar.options -underline 0 421 menu .workdir.menubar.options -tearoff 0 422 423 if { [info exists cvsmenu] || \ 424 [info exists usermenu] || \ 425 [info exists execmenu]} { 426 .workdir.menubar add cascade -label "User Defined" -menu .workdir.menubar.user -underline 0 427 menu .workdir.menubar.user -tearoff 0 428 gen_log:log T "Adding user defined menu" 429 } 430 .workdir.menubar add cascade -label "Go" -menu .workdir.menubar.goto -underline 0 431 menu .workdir.menubar.goto -tearoff 0 432 433 menu_std_help .workdir.menubar 434 435 # 436 # Create the Menus 437 # 438 439 # File 440 .workdir.menubar.file add command -label "Open Selection" -underline 0 \ 441 -command { workdir_edit_file [workdir_list_files] } 442 .workdir.menubar.file add command -label "Print Selected File" -underline 0 \ 443 -command { workdir_print_file [workdir_list_files ] } 444 .workdir.menubar.file add command -label "Make New Directory" -underline 0 \ 445 -command { file_input_and_do "New Directory" workdir_newdir} 446 .workdir.menubar.file add separator 447 .workdir.menubar.file add command -label "Browse Modules" -underline 0 \ 448 -command modbrowse_run 449 .workdir.menubar.file add command -label "Cleanup Directory" -underline 4 \ 450 -command workdir_cleanup 451 .workdir.menubar.file add separator 452 .workdir.menubar.file add command -label "Shell window" -underline 0 \ 453 -command { exec::new $cvscfg(shell) } 454 .workdir.menubar.file add separator 455 .workdir.menubar.file add command -label Close -underline 1 \ 456 -command {.workdir.close invoke} 457 .workdir.menubar.file add command -label Exit -underline 1 \ 458 -command { exit_cleanup 1 } 459 460 # CVS 461 .workdir.menubar.cvs add command -label "Update" -underline 0 \ 462 -command { \ 463 cvs_update {BASE} {Normal} {Remove} {recurse} {prune} {No} { } [workdir_list_files] } 464 .workdir.menubar.cvs add command -label "Update with Options" -underline 7 \ 465 -command cvs_update_options 466 .workdir.menubar.cvs add command -label "Commit/Checkin" -underline 0 \ 467 -command cvs_commit_dialog 468 .workdir.menubar.cvs add command -label "Add Files" -underline 0 \ 469 -command { add_dialog [workdir_list_files] } 470 .workdir.menubar.cvs add command -label "Add Recursively" \ 471 -command { addir_dialog [workdir_list_files] } 472 .workdir.menubar.cvs add command -label "Remove Files" -underline 0 \ 473 -command { subtract_dialog [workdir_list_files] } 474 .workdir.menubar.cvs add command -label "Remove Recursively" \ 475 -command { subtractdir_dialog [workdir_list_files] } 476 .workdir.menubar.cvs add command -label "Set Binary Flag" \ 477 -command { cvs_binary [workdir_list_files] } 478 .workdir.menubar.cvs add command -label "Unset Binary Flag" \ 479 -command { cvs_ascii [workdir_list_files] } 480 .workdir.menubar.cvs add command -label "Set Edit Flag (Edit)" -underline 15 \ 481 -command { cvs_edit [workdir_list_files] } 482 .workdir.menubar.cvs add command -label "Unset Edit Flag (Unedit)" -underline 11 \ 483 -command { cvs_unedit [workdir_list_files] } 484 .workdir.menubar.cvs add command -label "Tag Files" -underline 0 \ 485 -command { file_tag_dialog "tag" } 486 .workdir.menubar.cvs add command -label "Browse the Log Diagram" \ 487 -command { cvs_branches [workdir_list_files] } 488 .workdir.menubar.cvs add command -label "Resolve Conflicts" \ 489 -command { cvs_merge_conflict [workdir_list_files] } 490 .workdir.menubar.cvs add separator 491 .workdir.menubar.cvs add command -label "Release" \ 492 -command { release_dialog [workdir_list_files] } 493 .workdir.menubar.cvs add command -label "Join (Merge) Directory" \ 494 -underline 0 -command { cvs_directory_merge } 495 .workdir.menubar.cvs add command -label "Import CWD into Repository" \ 496 -underline 0 -command import_run 497 498 # SVN 499 .workdir.menubar.svn add command -label "Update" -underline 0 \ 500 -command {svn_update [workdir_list_files]} 501 .workdir.menubar.svn add command -label "Resolve (Un-mark Conflict)" -underline 0 \ 502 -command {svn_resolve [workdir_list_files]} 503 .workdir.menubar.svn add command -label "Commit/Checkin" -underline 0 \ 504 -command svn_commit_dialog 505 .workdir.menubar.svn add command -label "Add Files" -underline 0 \ 506 -command { add_dialog [workdir_list_files] } 507 .workdir.menubar.svn add command -label "Remove Files" -underline 0 \ 508 -command { subtract_dialog [workdir_list_files] } 509 .workdir.menubar.svn add command -label "Browse the Log Diagram" \ 510 -command { svn_branches [workdir_list_files] } 511 .workdir.menubar.svn add separator 512 .workdir.menubar.svn add command -label "Import CWD into Repository" \ 513 -underline 0 -command svn_import_run 514 515 # RCS 516 .workdir.menubar.rcs add command -label "Checkout" -underline 0 \ 517 -command { rcs_checkout [workdir_list_files] } 518 .workdir.menubar.rcs add command -label "Checkin" -underline 0 \ 519 -command { rcs_checkin [workdir_list_files] } 520 .workdir.menubar.rcs add command -label "Browse the Log Diagram" \ 521 -command { rcs_branches [workdir_list_files] } 522 523 # These commands will vary according to revision system. Does it still make sense to 524 # keep them in their own menu? 525 .workdir.menubar.reports add command -label "Check Directory" -underline 0 526 .workdir.menubar.reports add command -label "Status" -underline 0 527 .workdir.menubar.reports add command -label "Log" -underline 0 528 .workdir.menubar.reports add command -label "Annotate/Blame" -underline 0 529 .workdir.menubar.reports add command -label "Info" -underline 0 530 531 .workdir.menubar.options add checkbutton -label "Show hidden files" \ 532 -variable cvscfg(allfiles) -onvalue true -offvalue false \ 533 -command setup_dir 534 .workdir.menubar.options add checkbutton -label "Automatic directory status" \ 535 -variable cvscfg(auto_status) -onvalue true -offvalue false 536 .workdir.menubar.options add checkbutton -label "Confirmation Dialogs" \ 537 -variable cvscfg(confirm_prompt) -onvalue true -offvalue false 538 .workdir.menubar.options add separator 539 .workdir.menubar.options add checkbutton -label "Editor/Author/Locker Column" \ 540 -variable cvscfg(showeditcol) -onvalue true -offvalue false \ 541 -command { if {($incvs || $insvn || $inrcs) && $cvscfg(showeditcol)} { 542 DirCanvas:map_column .workdir.main editcol 543 } else { 544 DirCanvas:unmap_column .workdir.main editcol 545 } 546 } 547 .workdir.menubar.options add checkbutton -label "Status Column" \ 548 -variable cvscfg(showstatcol) -onvalue true -offvalue false \ 549 -command { if {($incvs || $insvn || $inrcs) && $cvscfg(showstatcol)} { 550 DirCanvas:map_column .workdir.main statcol 551 } else { 552 DirCanvas:unmap_column .workdir.main statcol 553 } 554 } 555 .workdir.menubar.options add checkbutton -label "Date Column" \ 556 -variable cvscfg(showdatecol) -onvalue true -offvalue false \ 557 -command { if {$cvscfg(showdatecol)} { 558 DirCanvas:map_column .workdir.main datecol 559 } else { 560 DirCanvas:unmap_column .workdir.main datecol 561 } 562 } 563 .workdir.menubar.options add radiobutton -label "Sort by Name" \ 564 -variable cvscfg(sortcol) -value filecol \ 565 -command "DirCanvas:sort_by_col .workdir.main filecol -decreasing" 566 .workdir.menubar.options add radiobutton -label "Sort by Status" \ 567 -variable cvscfg(sortcol) -value statcol \ 568 -command "DirCanvas:sort_by_col .workdir.main statcol -decreasing" 569 .workdir.menubar.options add separator 570 .workdir.menubar.options add checkbutton -label "Report->Check Shows Unknown Files" \ 571 -variable cvscfg(status_filter) -onvalue false -offvalue true 572 .workdir.menubar.options add checkbutton -label "Report->Check/Status are Recursive" \ 573 -variable cvscfg(recurse) -onvalue true -offvalue false 574 .workdir.menubar.options add cascade -label "Status Detail" \ 575 -menu .workdir.menubar.options.report_detail 576 .workdir.menubar.options add cascade -label "Log Detail" \ 577 -menu .workdir.menubar.options.logfile_detail 578 .workdir.menubar.options add separator 579 .workdir.menubar.options add checkbutton -label "Tracing On/Off" \ 580 -variable cvscfg(logging) -onvalue true -offvalue false \ 581 -command log_toggle 582 .workdir.menubar.options add cascade -label "Trace Level" \ 583 -menu .workdir.menubar.options.loglevel 584 .workdir.menubar.options add separator 585 .workdir.menubar.options add command -label "Save Options" -underline 0 \ 586 -command save_options 587 588 menu .workdir.menubar.options.loglevel 589 .workdir.menubar.options.loglevel add checkbutton -label "commands (C)" \ 590 -variable logclass(C) -onvalue "C" -offvalue "" \ 591 -command gen_log:changeclass 592 .workdir.menubar.options.loglevel add checkbutton -label "stderr (E)" \ 593 -variable logclass(E) -onvalue "E" -offvalue "" \ 594 -command gen_log:changeclass 595 .workdir.menubar.options.loglevel add checkbutton -label "stdout and file creation/deletion (F)"\ 596 -variable logclass(F) -onvalue "F" -offvalue "" \ 597 -command gen_log:changeclass 598 .workdir.menubar.options.loglevel add checkbutton -label "Function entry/exit (T)" \ 599 -variable logclass(T) -onvalue "T" -offvalue "" \ 600 -command gen_log:changeclass 601 .workdir.menubar.options.loglevel add checkbutton -label "Debugging (D)" \ 602 -variable logclass(D) -onvalue "D" -offvalue "" \ 603 -command gen_log:changeclass 604 605 menu .workdir.menubar.options.report_detail 606 .workdir.menubar.options.report_detail add radiobutton -label "Verbose" \ 607 -variable cvscfg(rdetail) -value "verbose" 608 .workdir.menubar.options.report_detail add radiobutton -label "Summary" \ 609 -variable cvscfg(rdetail) -value "summary" 610 .workdir.menubar.options.report_detail add radiobutton -label "Terse" \ 611 -variable cvscfg(rdetail) -value "terse" 612 613 menu .workdir.menubar.options.logfile_detail 614 .workdir.menubar.options.logfile_detail add radiobutton -label "Summary" \ 615 -variable cvscfg(ldetail) -value "summary" 616 .workdir.menubar.options.logfile_detail add radiobutton -label "Latest" \ 617 -variable cvscfg(ldetail) -value "latest" 618 .workdir.menubar.options.logfile_detail add radiobutton -label "Verbose" \ 619 -variable cvscfg(ldetail) -value "verbose" 620 621 .workdir.menubar.goto add command -label "Go Home" \ 622 -command {change_dir $cvscfg(home)} 623 .workdir.menubar.goto add command -label "Add Bookmark" \ 624 -command add_bookmark 625 .workdir.menubar.goto add command -label "Delete Bookmark" \ 626 -command delete_bookmark_dialog 627 .workdir.menubar.goto add separator 628 foreach mark [lsort [array names bookmarks]] { 629 # Backward compatibility. Value used to be a placeholder, is now a revsystem type 630 if {$bookmarks($mark) == "t"} {set bookmarks($mark) ""} 631 .workdir.menubar.goto add command -label "$mark $bookmarks($mark)" \ 632 -command "change_dir \"$mark\"" 633 } 634 635 636 # 637 # Add user commands to the menu. 638 # 639 if {[info exists cvsmenu]} { 640 foreach item [array names cvsmenu] { 641 .workdir.menubar.user add command -label $item \ 642 -command "eval cvs_usercmd $cvsmenu($item) \[workdir_list_files\]" 643 } 644 } 645 if {[info exists usermenu]} { 646 .workdir.menubar.user add separator 647 foreach item [array names usermenu] { 648 .workdir.menubar.user add command -label $item \ 649 -command "eval cvs_catchcmd $usermenu($item) \[workdir_list_files\]" 650 } 651 } 652 if {[info exists execmenu]} { 653 .workdir.menubar.user add separator 654 foreach item [array names execmenu] { 655 .workdir.menubar.user add command -label $item \ 656 -command "eval cvs_execcmd $execmenu($item) \[workdir_list_files\]" 657 } 658 } 659 gen_log:log T "LEAVE" 660} 661 662proc workdir_list_files {} { 663 global cvscfg 664 global cvsglb 665 666 gen_log:log T "ENTER (cvsglb(current_selection) = $cvsglb(current_selection))" 667 668 for {set i 0} {$i < [llength $cvsglb(current_selection)]} {incr i} { 669 set item [lindex $cvsglb(current_selection) $i] 670 regsub {^no file } $item "" item 671 # regsub here causes file isfile to return 0. You have to do it in each 672 # proc, just before the cvs command, after file tests have been done. 673 #regsub -all {\$} $item {\$} item 674 set cvsglb(current_selection) [lreplace $cvsglb(current_selection) $i $i $item] 675 } 676 gen_log:log T "LEAVE -- ($cvsglb(current_selection))" 677 return $cvsglb(current_selection) 678} 679 680proc workdir_edit_command {file} { 681 global cvscfg 682 683 gen_log:log T "ENTER ($file)" 684 if {[info exists cvscfg(editors)]} { 685 foreach {editor pattern} $cvscfg(editors) { 686 if {[string match $pattern $file]} { 687 return "$editor \"$file\"" 688 } 689 } 690 } 691 return "$cvscfg(editor) \"$file\"" 692} 693 694proc workdir_newdir {file} { 695 global cvscfg 696 697 gen_log:log T "ENTER ($file)" 698 699 file mkdir $file 700 701 if {$cvscfg(auto_status)} { 702 setup_dir 703 } 704 gen_log:log T "LEAVE" 705} 706 707proc workdir_edit_file {args} { 708 global cvscfg 709 global cwd 710 711 gen_log:log T "ENTER ($args)" 712 713 set filelist [join $args] 714 if {$filelist == ""} { 715 file_input_and_do "Edit File" workdir_edit_file 716 return 717 } 718 719 gen_log:log D "$filelist" 720 foreach file $filelist { 721 if {[file isdirectory $file]} { 722 change_dir "$file" 723 } else { 724 if {![file exists $file] || [file isfile $file]} { 725 # If the file doesn't exist it's tempting to touch the file and 726 # trigger a reread, but is an empty file of this type valid? 727 regsub -all {\$} $file {\$} file 728 set commandline [workdir_edit_command $file] 729 set editcmd [exec::new $commandline] 730 } else { 731 cvsfail "$file is not a plain file" .workdir 732 } 733 } 734 } 735 gen_log:log T "LEAVE" 736} 737 738proc workdir_view_file {args} { 739 global cvscfg 740 global cwd 741 742 gen_log:log T "ENTER ($args)" 743 744 set filelist [join $args] 745 if {$filelist == ""} { 746 cvsfail "Please select some files to view first!" .workdir 747 return 748 } 749 750 gen_log:log D "$filelist" 751 foreach file $filelist { 752 set filelog "" 753 if {[file isfile $file]} { 754 #regsub -all {\$} $file {\$} file 755 gen_log:log F "OPEN $file" 756 set f [open $file] 757 while { [eof $f] == 0 } { 758 append filelog [gets $f] 759 append filelog "\n" 760 } 761 view_output::new "$file" $filelog 762 } else { 763 cvsfail "$file is not a plain file" .workdir 764 } 765 } 766 gen_log:log T "LEAVE" 767} 768 769# Let the user mark directories they visit often 770proc add_bookmark { } { 771 global incvs inrcs insvn 772 global bookmarks 773 774 gen_log:log T "ENTER" 775 set dir [pwd] 776 regsub -all {\$} $dir {\$} dir 777 778 gen_log:log D "directory $dir" 779 foreach mark [array names bookmarks] { 780 gen_log:log D " $mark \"$bookmarks($mark)\"" 781 } 782 783 if {[info exists bookmarks($dir)]} { 784 .workdir.menubar.goto delete "$dir $bookmarks($dir)" 785 } 786 set rtype "" 787 if {$inrcs} { 788 set rtype "(RCS)" 789 } elseif {$incvs} { 790 set rtype "(CVS)" 791 } elseif {$insvn} { 792 set rtype "(SVN)" 793 } 794 set bookmarks($dir) $rtype 795 .workdir.menubar.goto add command -label "$dir $rtype" \ 796 -command "change_dir \"$dir\"" 797 798 gen_log:log T "LEAVE" 799} 800 801# A listbox to choose a bookmark to delete 802proc delete_bookmark_dialog { } { 803 global cvscfg 804 global cvsglb 805 global bookmarks 806 807 gen_log:log T "ENTER" 808 set maxlbl 0 809 foreach mark [array names bookmarks] { 810 gen_log:log D " $mark $bookmarks($mark)" 811 set len [string length "$mark $bookmarks($mark)"] 812 if {$len > $maxlbl} { 813 set maxlbl $len 814 } 815 } 816 817 set wname .workdir.bookmarkedit 818 toplevel $wname 819 grab set $wname 820 wm title $wname "Delete Bookmarks" 821 listbox $wname.lbx -selectmode multiple \ 822 -font $cvscfg(listboxfont) -width $maxlbl 823 pack $wname.lbx -ipadx 10 -ipady 10 -expand y -fill both 824 foreach mark [lsort [array names bookmarks]] { 825 $wname.lbx insert end "$mark $bookmarks($mark)" 826 } 827 frame $wname.buttons 828 pack $wname.buttons -side top -fill x 829 button $wname.delete -text "Delete" \ 830 -command "delete_bookmark $wname" 831 832 button $wname.close -text "Done" \ 833 -command " 834 grab release $wname 835 destroy $wname 836 exit_cleanup 0" 837 pack $wname.delete $wname.close -in $wname.buttons \ 838 -side right -ipadx 2 -ipady 2 -padx 4 -pady 4 \ 839 -expand y 840 841 gen_log:log T "LEAVE" 842} 843 844# Do the actual deletion of the bookmark 845proc delete_bookmark {w} { 846 global bookmarks 847 848 gen_log:log T "ENTER ($w)" 849 set items [$w.lbx curselection] 850 foreach item $items { 851 set itemstring [$w.lbx get $item] 852 #set dir [join [lrange $itemstring 0 end-1]] 853 regsub {\s+$} $itemstring {} dir 854 regsub {\s+\([A-Z][A-Z][A-Z]\)$} $dir {} dir 855 gen_log:log D "$item \"$itemstring\"" 856 gen_log:log D " directory \"$dir\"" 857 unset bookmarks($dir) 858 $w.lbx delete $item 859 .workdir.menubar.goto delete $itemstring 860 } 861 gen_log:log T "LEAVE" 862} 863 864proc change_dir {new_dir} { 865 global cwd 866 867 gen_log:log T "ENTER ($new_dir)" 868 if {![file exists $new_dir]} { 869 set cwd [pwd] 870 cvsfail "Directory $new_dir doesn\'t exist!" .workdir 871 return 872 } 873 set cwd $new_dir 874 # Deleting the tree discards the saved scroll position 875 # so we start with yview 0 in a new directory 876 DirCanvas:deltree .workdir.main 877 setup_dir 878 879 gen_log:log T "LEAVE" 880} 881 882proc auto_setup_dir {command} { 883 global cvscfg 884 885 if {$cvscfg(auto_status)} { 886 $command\::wait 887 setup_dir 888 } else { 889 after 0 "$command\::wait; $command\::destroy" 890 } 891} 892 893proc setup_dir { } { 894 # 895 # Call this when entering a directory. It puts all of the file names 896 # in the listbox, and reads the directory. 897 # 898 global cwd 899 global module_dir 900 global incvs 901 global insvn 902 global inrcs 903 global cvscfg 904 global current_tagname 905 global cvsglb 906 907 gen_log:log T "ENTER" 908 909 set savyview 0 910 if { ! [winfo exists .workdir.main] } { 911 workdir_setup 912 return 913 } else { 914 if {[winfo exists .workdir.main.filecol.list]} { 915 set savyview [lindex [.workdir.main.filecol.list yview] 0] 916 } 917 DirCanvas:deltree .workdir.main 918 } 919 gen_log:log D "YVIEW $savyview" 920 921 if {![file isdirectory $cwd]} { 922 gen_log:log D "$cwd is not a directory" 923 gen_log:log T "LEAVE -- $cwd is not a directory" 924 return 925 } 926 927 cd $cwd 928 gen_log:log F "CD [pwd]" 929 930 set module_dir "" 931 set current_tagname "" 932 ::picklist::used directory [pwd] 933 934 foreach {incvs insvn inrcs} [cvsroot_check [pwd]] { break } 935 gen_log:log D "incvs $incvs inrcs $inrcs insvn $insvn" 936 937 .workdir.top.bmodbrowse configure -image Modules 938 .workdir.top.lmodule configure -text "Path" 939 .workdir.top.ltagname configure -text "Tag" 940 # Start with the revision-control menus disabled 941 .workdir.menubar entryconfigure "CVS" -state normal 942 .workdir.menubar entryconfigure "SVN" -state normal 943 .workdir.menubar entryconfigure "RCS" -state normal 944 .workdir.menubar.reports entryconfigure 0 -state disabled 945 .workdir.menubar.reports entryconfigure 1 -state disabled 946 .workdir.menubar.reports entryconfigure 2 -state disabled 947 .workdir.menubar.reports entryconfigure 3 -state disabled 948 .workdir.menubar.reports entryconfigure 4 -state disabled 949 # Start with the revision-control buttons disabled and the 950 .workdir.bottom.buttons.dirfuncs.bcheckdir configure -state disabled 951 foreach widget [grid slaves .workdir.bottom.buttons.cvsfuncs ] { 952 $widget configure -state disabled 953 } 954 foreach widget [grid slaves .workdir.bottom.buttons.cvsfuncs ] { 955 $widget configure -state disabled 956 } 957 foreach widget [grid slaves .workdir.bottom.buttons.oddfuncs ] { 958 $widget configure -state disabled 959 } 960 961 # Now enable them depending on where we are 962 if {$inrcs} { 963 # Top 964 .workdir.top.lcvsroot configure -text "RCS *,v" 965 .workdir.top.tcvsroot configure -textvariable cvscfg(rcsdir) 966 # Buttons 967 .workdir.bottom.buttons.dirfuncs.bcheckdir configure -state normal \ 968 -command { rcs_check } 969 .workdir.bottom.buttons.cvsfuncs.bdiff configure -state normal 970 .workdir.bottom.buttons.cvsfuncs.blogfile configure -state normal \ 971 -command { rcs_branches [workdir_list_files] } 972 .workdir.bottom.buttons.cvsfuncs.bfilelog configure -state normal \ 973 -command { rcs_log [workdir_list_files] } 974 .workdir.bottom.buttons.cvsfuncs.bupdate configure -state normal \ 975 -command { rcs_checkout [workdir_list_files] } 976 .workdir.bottom.buttons.cvsfuncs.bcheckin configure -state normal \ 977 -command { rcs_checkin [workdir_list_files] } 978 .workdir.bottom.buttons.cvsfuncs.brevert configure -state normal \ 979 -command { rcs_revert [workdir_list_files] } 980 .workdir.bottom.buttons.oddfuncs.block configure -state normal \ 981 -command { rcs_lock lock [workdir_list_files] } 982 .workdir.bottom.buttons.oddfuncs.bunlock configure -state normal \ 983 -command { rcs_lock unlock [workdir_list_files] } 984 # Menus 985 .workdir.menubar entryconfigure "CVS" -state disabled 986 .workdir.menubar entryconfigure "SVN" -state disabled 987 .workdir.menubar entryconfigure "RCS" -state normal 988 # Reports Menu 989 # Check Directory (log & rdiff) 990 .workdir.menubar.reports entryconfigure 0 -state normal \ 991 -command { rcs_check } 992 .workdir.menubar.reports entryconfigure 1 -state disabled 993 # Log (rlog) 994 .workdir.menubar.reports entryconfigure 2 -state normal \ 995 -command { rcs_log [workdir_list_files] } 996 .workdir.menubar.reports entryconfigure 3 -state disabled 997 .workdir.menubar.reports entryconfigure 4 -state disabled 998 } elseif {$insvn} { 999 # Top 1000 .workdir.top.bmodbrowse configure -image Modules_svn \ 1001 -command {modbrowse_run svn} 1002 .workdir.top.lmodule configure -text "Path" 1003 .workdir.top.ltagname configure -text "Tag" 1004 .workdir.top.lcvsroot configure -text "SVN URL" 1005 .workdir.top.tcvsroot configure -textvariable cvscfg(url) 1006 # Buttons 1007 .workdir.bottom.buttons.dirfuncs.bcheckdir configure -state normal \ 1008 -command { svn_check [workdir_list_files] } 1009 .workdir.bottom.buttons.cvsfuncs.bjoin configure -state normal \ 1010 -command { svn_branches . } 1011 .workdir.bottom.buttons.cvsfuncs.bdiff configure -state normal 1012 .workdir.bottom.buttons.cvsfuncs.blogfile configure -state normal \ 1013 -command { svn_branches [workdir_list_files] } 1014 .workdir.bottom.buttons.cvsfuncs.bfilelog configure -state normal \ 1015 -command { svn_log [workdir_list_files] } 1016 .workdir.bottom.buttons.cvsfuncs.bannotate configure -state normal \ 1017 -command { svn_annotate BASE [workdir_list_files] } 1018 .workdir.bottom.buttons.cvsfuncs.bconflict configure -state normal \ 1019 -command { foreach f [workdir_list_files] {svn_merge_conflict \"$f\"} } 1020 .workdir.bottom.buttons.cvsfuncs.badd_files configure -state normal 1021 .workdir.bottom.buttons.cvsfuncs.bremove configure -state normal 1022 .workdir.bottom.buttons.cvsfuncs.bupdate configure -state normal \ 1023 -command { svn_update [workdir_list_files] } 1024 .workdir.bottom.buttons.cvsfuncs.bupdateopts configure -state normal \ 1025 -command { svn_update_options } 1026 .workdir.bottom.buttons.cvsfuncs.bcheckin configure -state normal \ 1027 -command svn_commit_dialog 1028 .workdir.bottom.buttons.cvsfuncs.brevert configure -state normal \ 1029 -command { svn_revert [workdir_list_files] } 1030 .workdir.bottom.buttons.cvsfuncs.btag configure -state normal 1031 .workdir.bottom.buttons.cvsfuncs.bbranchtag configure -state normal 1032 .workdir.bottom.buttons.oddfuncs.block configure -state normal \ 1033 -command { svn_lock lock [workdir_list_files] } 1034 .workdir.bottom.buttons.oddfuncs.bunlock configure -state normal \ 1035 -command { svn_lock unlock [workdir_list_files] } 1036 # Menus 1037 .workdir.menubar entryconfigure "CVS" -state disabled 1038 .workdir.menubar entryconfigure "SVN" -state normal 1039 .workdir.menubar entryconfigure "RCS" -state disabled 1040 # Reports Menu 1041 # Check Directory (svn status) 1042 .workdir.menubar.reports entryconfigure 0 -state normal \ 1043 -command { svn_check {} } 1044 # Status (svn status <filelist>) 1045 .workdir.menubar.reports entryconfigure 1 -state normal \ 1046 -command { svn_check [workdir_list_files] } 1047 # Log (svn log) 1048 .workdir.menubar.reports entryconfigure 2 -state normal \ 1049 -command { svn_log [workdir_list_files] } 1050 # Annotate/Blame (svn blame) 1051 .workdir.menubar.reports entryconfigure 3 -state normal \ 1052 -command { svn_annotate BASE [workdir_list_files] } 1053 # Info (svn info) 1054 .workdir.menubar.reports entryconfigure 4 -state normal \ 1055 -command { svn_info [workdir_list_files] } 1056 } elseif {$incvs} { 1057 # Top 1058 .workdir.top.bmodbrowse configure -image Modules_cvs \ 1059 -command {modbrowse_run cvs} 1060 .workdir.top.lmodule configure -text "Module" 1061 .workdir.top.ltagname configure -text "Tag" 1062 .workdir.top.lcvsroot configure -text "CVSROOT" 1063 .workdir.top.tcvsroot configure -textvariable cvscfg(cvsroot) 1064 # Buttons 1065 .workdir.bottom.buttons.dirfuncs.bcheckdir configure -state normal \ 1066 -command { cvs_check [workdir_list_files] } 1067 .workdir.bottom.buttons.cvsfuncs.bjoin configure -state normal \ 1068 -command cvs_joincanvas 1069 .workdir.bottom.buttons.cvsfuncs.bdiff configure -state normal 1070 .workdir.bottom.buttons.cvsfuncs.bconflict configure -state normal \ 1071 -command { cvs_merge_conflict [workdir_list_files] } 1072 .workdir.bottom.buttons.cvsfuncs.bfilelog configure -state normal \ 1073 -command { cvs_log [workdir_list_files] } 1074 .workdir.bottom.buttons.cvsfuncs.bannotate configure -state normal \ 1075 -command { cvs_annotate $current_tagname [workdir_list_files] } 1076 .workdir.bottom.buttons.cvsfuncs.badd_files configure -state normal 1077 .workdir.bottom.buttons.cvsfuncs.bremove configure -state normal 1078 .workdir.bottom.buttons.cvsfuncs.bupdate configure -state normal \ 1079 -command { \ 1080 cvs_update {BASE} {Normal} {Remove} {recurse} {prune} {No} { } [workdir_list_files] } 1081 .workdir.bottom.buttons.cvsfuncs.bupdateopts configure -state normal \ 1082 -command { cvs_update_options } 1083 .workdir.bottom.buttons.cvsfuncs.bcheckin configure -state normal \ 1084 -command cvs_commit_dialog 1085 .workdir.bottom.buttons.cvsfuncs.brevert configure -state normal \ 1086 -command {cvs_revert [workdir_list_files] } 1087 .workdir.bottom.buttons.cvsfuncs.btag configure -state normal 1088 .workdir.bottom.buttons.cvsfuncs.bbranchtag configure -state normal 1089 .workdir.bottom.buttons.cvsfuncs.blogfile configure -state normal \ 1090 -command { cvs_branches [workdir_list_files] } 1091 .workdir.bottom.buttons.cvsfuncs.bfilelog configure -state normal \ 1092 -command { cvs_log [workdir_list_files] } 1093 if {$cvscfg(econtrol)} { 1094 .workdir.bottom.buttons.oddfuncs.bcvsedit_files configure -state normal 1095 .workdir.bottom.buttons.oddfuncs.bunedit_files configure -state normal 1096 } 1097 if {$cvscfg(cvslock)} { 1098 .workdir.bottom.buttons.oddfuncs.block configure -state normal \ 1099 -command { cvs_lock lock [workdir_list_files] } 1100 .workdir.bottom.buttons.oddfuncs.bunlock configure -state normal \ 1101 -command { cvs_lock unlock [workdir_list_files] } 1102 } 1103 # Menus 1104 .workdir.menubar entryconfigure "CVS" -state normal 1105 .workdir.menubar entryconfigure "SVN" -state disabled 1106 .workdir.menubar entryconfigure "RCS" -state disabled 1107 # Reports Menu 1108 # Check Directory (cvs -n -q update) 1109 .workdir.menubar.reports entryconfigure 0 -state normal \ 1110 -command { cvs_check {} } 1111 # Status (cvs -Q status) 1112 .workdir.menubar.reports entryconfigure 1 -state normal \ 1113 -command { cvs_status [workdir_list_files] } 1114 # Log (cvs log) 1115 .workdir.menubar.reports entryconfigure 2 -state normal \ 1116 -command { cvs_log [workdir_list_files] } 1117 # Annotate/Blame (cvs annotate) 1118 .workdir.menubar.reports entryconfigure 3 -state normal \ 1119 -command { cvs_annotate $current_tagname [workdir_list_files] } 1120 .workdir.menubar.reports entryconfigure 4 -state disabled 1121 } 1122 1123 DirCanvas:create .workdir.main 1124 pack .workdir.main.pw -side bottom -fill both -expand yes 1125 1126 set cvsglb(current_selection) {} 1127 1128 set cvscfg(ignore_file_filter) $cvsglb(default_ignore_filter) 1129 1130 if { [ file exists ".cvsignore" ] } { 1131 set fileId [ open ".cvsignore" "r" ] 1132 while { [ eof $fileId ] == 0 } { 1133 gets $fileId line 1134 append cvscfg(ignore_file_filter) " $line" 1135 } 1136 close $fileId 1137 } else { 1138 if {$insvn} { 1139 # Have to do eval exec because we need the error output 1140 set command "svn propget svn:ignore" 1141 gen_log:log C "$command" 1142 set ret [catch {eval "exec $command"} output] 1143 if {$ret} { 1144 cvsfail $output 1145 return 1146 } 1147 foreach infoline [split $output "\n"] { 1148 append cvscfg(ignore_file_filter) " $infoline" 1149 } 1150 } 1151 } 1152 1153 set filelist [ getFiles ] 1154 directory_list $filelist 1155 # Update, otherwise it won't be mapped before we restore the scroll position 1156 update 1157 DirCanvas:yview_windows .workdir.main $savyview 1158 1159 gen_log:log T "LEAVE" 1160} 1161 1162proc directory_list { filenames } { 1163 global module_dir 1164 global incvs 1165 global insvn 1166 global inrcs 1167 global cvs 1168 global cwd 1169 global cvscfg 1170 global cvsglb 1171 global cmd 1172 global Filelist 1173 1174 gen_log:log T "ENTER ($filenames)" 1175 1176 if {[info exists Filelist]} { 1177 unset Filelist 1178 } 1179 1180 busy_start .workdir.main 1181 1182 #gen_log:log F "processing files in the local directory" 1183 set cwd [pwd] 1184 set my_cwd $cwd 1185 1186 # If we have commands running they were for a different directory 1187 # and won't be needed now. (i.e. this is a recursive invocation 1188 # triggered by a button click) 1189 if {[info exists cmd(cvs_status)]} { 1190 catch {$cmd(cvs_status)\::abort} 1191 catch {unset cmd(cvs_status)} 1192 } 1193 if {[info exists cmd(cvs_editors)]} { 1194 catch {$cmd(cvs_editors)\::abort} 1195 catch {unset cmd(cvs_editors)} 1196 } 1197 1198 # Select from those files only the ones we want (e.g., no CVS dirs) 1199 foreach i $filenames { 1200 if { $i == "." || $i == ".."} { 1201 gen_log:log D "SKIPPING $i" 1202 continue 1203 } 1204 if {[file isdirectory $i]} { 1205 if {[isCmDirectory $i]} { 1206 # Read the bookkeeping files but don't list the directory 1207 if {$i == "CVS" || $i == ".svn" || $i == "RCS"} { 1208 continue 1209 } 1210 } 1211 if {[file exists [file join $i "CVS"]]} { 1212 set Filelist($i:status) "<directory:CVS>" 1213 } elseif {[file exists [file join $i ".svn"]]} { 1214 set Filelist($i:status) "<directory:SVN>" 1215 } elseif {[file exists [file join $i "RCS"]]} { 1216 set Filelist($i:status) "<directory:RCS>" 1217 } else { 1218 set Filelist($i:status) "<directory>" 1219 } 1220 } else { 1221 if {$incvs} { 1222 set Filelist($i:status) "Not managed by CVS" 1223 } else { 1224 set Filelist($i:status) "<file>" 1225 } 1226 } 1227 set Filelist($i:wrev) "" 1228 set Filelist($i:stickytag) "" 1229 set Filelist($i:option) "" 1230 # Prepending ./ to the filename prevents tilde expansion 1231 catch {set Filelist($i:date) \ 1232 [clock format [file mtime ./$i] -format $cvscfg(dateformat)]} 1233 } 1234 1235 gen_log:log D "incvs=$incvs insvn=$insvn inrcs=$inrcs" 1236 if {$incvs} { 1237 DirCanvas:headtext .workdir.main "editors" 1238 cvs_workdir_status 1239 } 1240 1241 if {$inrcs} { 1242 DirCanvas:headtext .workdir.main "locked by" 1243 rcs_workdir_status 1244 } 1245 1246 if {$insvn} { 1247 DirCanvas:headtext .workdir.main "author" 1248 svn_workdir_status 1249 } 1250 1251 gen_log:log D "Sending all files to the canvas" 1252 foreach i [array names Filelist *:status] { 1253 regsub {:status$} $i "" j 1254 # If it's locally removed or missing, it may not have 1255 # gotten a date especially on a remote client. 1256 if {! [info exists Filelist($j:date)]} { 1257 set Filelist($j:date) "" 1258 } 1259 DirCanvas:newitem .workdir.main "$j" 1260 } 1261 1262 busy_done .workdir.main 1263 1264 gen_log:log T "LEAVE" 1265} 1266 1267proc workdir_cleanup {} { 1268 global cvscfg 1269 1270 gen_log:log T "ENTER" 1271 set rmitem "" 1272 set list [ split $cvscfg(clean_these) " " ] 1273 foreach pattern $list { 1274 gen_log:log D "pattern $pattern" 1275 if { $pattern != "" } { 1276 set items [lsort [glob -nocomplain $pattern]] 1277 gen_log:log D "$items" 1278 if {[llength $items] != 0} { 1279 append rmitem " [concat $items]" 1280 } 1281 } 1282 } 1283 1284 if {$rmitem != ""} { 1285 if { [ are_you_sure "You are about to delete:\n" $rmitem] == 1 } { 1286 gen_log:log F "DELETE $rmitem" 1287 eval file delete -force -- $rmitem 1288 } 1289 } else { 1290 gen_log:log F "No files to delete" 1291 cvsok "Nothing matched $cvscfg(clean_these)" .workdir 1292 return 1293 } 1294 setup_dir 1295 gen_log:log T "LEAVE" 1296} 1297 1298proc workdir_delete_file {args} { 1299 global cvscfg 1300 1301 gen_log:log T "ENTER ($args)" 1302 1303 set filelist [join $args] 1304 if {$filelist == ""} { 1305 cvsfail "Please select some files to delete first!" .workdir 1306 return 1307 } 1308 1309 if { [ are_you_sure "This will delete these files from your local, working directory:\n" $filelist ] == 1 } { 1310 gen_log:log F "DELETE $filelist" 1311 eval file delete -force -- $filelist 1312 setup_dir 1313 } 1314 gen_log:log T "LEAVE" 1315} 1316 1317proc are_you_sure {mess args} { 1318# 1319# General posting message 1320# 1321 global cvscfg 1322 1323 gen_log:log T "ENTER ($mess $args)" 1324 1325 set filelist [join $args] 1326 if {$cvscfg(confirm_prompt)} { 1327 append mess "\n" 1328 set indent " " 1329 1330 foreach item $filelist { 1331 if { $item != {} } { 1332 append mess " $indent" 1333 append mess " $item\n" 1334 } 1335 } 1336 append mess "\nAre you sure?" 1337 if {[cvsconfirm $mess .workdir] != "ok"} { 1338 gen_log:log T "LEAVE 0" 1339 return 0 1340 } 1341 } 1342 gen_log:log T "LEAVE 1" 1343 return 1 1344} 1345 1346proc workdir_print_file {args} { 1347 global cvscfg 1348 1349 gen_log:log T "ENTER ($args)" 1350 1351 set filelist [join $args] 1352 if {$filelist == ""} { 1353 cvsfail "Please select some files to print first!" .workdir 1354 return 1355 } 1356 1357 set mess "This will print these files:\n\n" 1358 foreach file $filelist { 1359 append mess " $file\n" 1360 } 1361 append mess "\nUsing $cvscfg(print_cmd)\n" 1362 append mess "\nAre you sure?" 1363 if {[cvsconfirm $mess .workdir] == "ok"} { 1364 set final_result "" 1365 foreach file $filelist { 1366 set commandline [concat $cvscfg(print_cmd) \"$file\"] 1367 exec::new $commandline 1368 } 1369 } 1370 gen_log:log T "LEAVE" 1371} 1372 1373proc cvsroot_check { dir } { 1374 global cvscfg 1375 global cvsglb 1376 1377 gen_log:log T "ENTER ($dir)" 1378 1379 foreach {incvs insvn inrcs} {0 0 0} {break} 1380 1381 if {[file isfile [file join $dir CVS Root]]} { 1382 set incvs [ read_cvs_dir [file join $dir CVS] ] 1383 } elseif {! [catch {eval "exec svn info"}]} { 1384 set insvn [ read_svn_dir $dir ] 1385 } else { 1386 set rcsdir [file join $dir RCS] 1387 if {[file exists $rcsdir]} { 1388 set cvscfg(rcsdir) $rcsdir 1389 set inrcs 1 1390 } elseif {[llength [glob -nocomplain -dir $dir *,v]] > 0} { 1391 set inrcs 1 1392 set cvscfg(rcsdir) $dir 1393 } else { 1394 set cvscfg(rcsdir) "" 1395 } 1396 } 1397 1398 if {$inrcs} { 1399 # Make sure we have rcs, and bag this (silently) if we don't 1400 set command "rcs -V" 1401 gen_log:log C "$command" 1402 set ret [catch {eval "exec $command"} raw_rcs_log] 1403 if {$ret} { 1404 gen_log:log D "$raw_rcs_log" 1405 if [string match {*Unknown option:*} $raw_rcs_log] { 1406 # An old version of RCS, but it's here 1407 set inrcs 1 1408 } else { 1409 set inrcs 0 1410 } 1411 } 1412 } 1413 1414 gen_log:log T "LEAVE ($incvs $insvn $inrcs)" 1415 return [list $incvs $insvn $inrcs] 1416} 1417 1418proc isCmDirectory { file } { 1419 #gen_log:log T "ENTER ($file)" 1420 switch -- $file { 1421 "CVS" - 1422 "RCS" - 1423 ".svn" - 1424 "SCCS" { set value 1 } 1425 default { set value 0 } 1426 } 1427 #gen_log:log T "LEAVE ($value)" 1428 return $value 1429} 1430 1431# Get the files in the current working directory. Use the file_filter 1432# values Add hidden files if desired by the user. Sort them to match 1433# the ordering that will be returned by cvs commands (this matches the 1434# default ls ordering.). 1435proc getFiles { } { 1436 global cvscfg 1437 global cvsglb 1438 1439 gen_log:log T "ENTER" 1440 set filelist "" 1441 1442 # make sure the file filter is at least set to "*". 1443 if { $cvscfg(file_filter) == "" } { 1444 set cvscfg(file_filter) "* .svn" 1445 } 1446 1447 # get the initial file list, including hidden if requested 1448 if {$cvscfg(allfiles)} { 1449 # get hidden as well 1450 foreach item $cvscfg(file_filter) { 1451 set filelist [ concat [ glob -nocomplain .$item $item ] $filelist ] 1452 } 1453 } else { 1454 foreach item $cvscfg(file_filter) { 1455 set filelist [ concat [ glob -nocomplain $item ] $filelist ] 1456 } 1457 } 1458 #gen_log:log D "filelist ($filelist)" 1459 1460 # ignore files if requested 1461 if { $cvscfg(ignore_file_filter) != "" } { 1462 foreach item $cvscfg(ignore_file_filter) { 1463 # for each pattern 1464 if { $item != "*" } { 1465 # if not "*" 1466 while { [set idx [lsearch $filelist $item]] != -1 } { 1467 # for each occurence, delete 1468 catch { set filelist [ lreplace $filelist $idx $idx ] } 1469 } 1470 } 1471 } 1472 } 1473 1474 # make sure "." is always in the list for 'cd' purposes 1475 if { ( [ lsearch -exact $filelist "." ] == -1 ) } { 1476 set filelist [ concat "." $filelist ] 1477 } 1478 1479 # make sure ".." is always in the list for 'cd' purposes 1480 if { ( [ lsearch -exact $filelist ".." ] == -1 ) } { 1481 set filelist [ concat ".." $filelist ] 1482 } 1483 1484 # sort it 1485 set filelist [ lsort $filelist ] 1486 1487 # if this directory is under CVS and CVS is not in the list, add it. Its 1488 # presence is needed for later processing 1489 if { ( [ file exists "CVS" ] ) && 1490 ( [ lsearch -exact $filelist "CVS" ] == -1 ) } { 1491 #puts "********* added CVS" 1492 catch { set filelist [ concat "CVS" $filelist ] } 1493 } 1494 1495 set cvscfg(ignore_file_filter) $cvsglb(default_ignore_filter) 1496 gen_log:log T "return ($filelist)" 1497 return $filelist 1498} 1499 1500proc log_toggle { } { 1501 global cvscfg 1502 1503 if {$cvscfg(logging)} { 1504 gen_log:init 1505 } else { 1506 gen_log:quit 1507 } 1508} 1509 1510proc exit_cleanup { force } { 1511 global cvscfg 1512 1513 # Count the number of toplevels that are currently interacting 1514 # with the user (i.e. exist and are not withdrawn) 1515 set wlist {} 1516 foreach w [winfo children .] { 1517 if {[wm state $w] != {withdrawn}} { 1518 lappend wlist $w 1519 } 1520 } 1521 1522 if {$force == 0 && [llength $wlist] != 0 \ 1523 && $wlist != {.trace} && $wlist != {.bgerrorTrace}} { 1524 return 1525 } 1526 1527 # If toplevel windows exist ask them to close gracefully if possible 1528 foreach w $wlist { 1529 # Except .trace! 1530 if {$w != {.trace}} { 1531 catch {$w.close invoke} 1532 } else { 1533 # Invoking trace's close turns off logging. We don't want that, 1534 # but we do want to save its geometry. 1535 if {[winfo exists .trace]} { 1536 set cvscfg(tracgeom) [wm geometry .trace] 1537 } 1538 } 1539 } 1540 1541 save_options 1542 set pid [pid] 1543 gen_log:log F "DELETE $cvscfg(tmpdir)/cvstmpdir.$pid" 1544 catch {file delete -force [file join $cvscfg(tmpdir) cvstmpdir.$pid]} 1545 exit 1546} 1547 1548proc save_options { } { 1549# 1550# Save the options which are configurable from the GUI 1551# 1552 global cvscfg 1553 global logcfg 1554 global bookmarks 1555 1556 gen_log:log T "ENTER" 1557 1558 # There are two kinds of options we can set 1559 set BOOLopts { allfiles auto_status confirm_prompt \ 1560 showstatcol showdatecol showeditcol auto_tag \ 1561 status_filter recurse logging blame_linenums} 1562 set STRGopts { file_filter ignore_file_filter clean_these \ 1563 printer rdetail ldetail log_classes lastdir sortcol \ 1564 workgeom modgeom loggeom tracgeom editor editorargs} 1565 1566 # Plus the logcanvas options 1567 set LOGopts [concat [array names logcfg show_*] scale] 1568 1569 # set this to current directory, so we'll add it to the menu next time 1570 if ([catch pwd]) { 1571 return 1572 } 1573 set cvscfg(lastdir) [pwd] 1574 1575 if {[info exists cvscfg(editorargs)] } { 1576 # editorargs is no longer necessary 1577 if {$cvscfg(editorargs) != ""} { 1578 set cvscfg(editor) [concat $cvscfg(editor) $cvscfg(editorargs)] 1579 } 1580 unset cvscfg(editorargs) 1581 } 1582 1583 # Save the list so we can keep track of what we've done 1584 set BOOLset $BOOLopts 1585 set STRGset $STRGopts 1586 set LOGset $LOGopts 1587 1588 set optfile [file join $cvscfg(home) .tkcvs] 1589 set bakfile [file join $cvscfg(home) .tkcvs.bak] 1590 # Save the old .tkcvs file 1591 gen_log:log F "MOVE $optfile $bakfile" 1592 catch {file rename -force $optfile $bakfile} 1593 1594 gen_log:log F "OPEN $optfile" 1595 if {[catch {set fo [open $optfile w]}]} { 1596 cvsfail "Cannot open $optfile for writing" .workdir 1597 return 1598 } 1599 gen_log:log F "OPEN $bakfile" 1600 1601 if {! [catch {set fi [open $bakfile r]}]} { 1602 while { [eof $fi] == 0 } { 1603 gets $fi line 1604 set match 0 1605 if {[regexp {^#} $line]} { 1606 # Don't try to scan comments. 1607 #gen_log:log D "PASSING \"$line\"" 1608 puts $fo "$line" 1609 continue 1610 } elseif {[string match "*set *bookmarks*" $line]} { 1611 # Discard old bookmarks 1612 continue 1613 } else { 1614 foreach opt $BOOLopts { 1615 if {! [info exists cvscfg($opt)]} { continue } 1616 if {[string match "*set *cvscfg($opt)*" $line]} { 1617 # Print it and remove it from the list 1618 gen_log:log D "REPLACING $line w/ set cvscfg($opt) $cvscfg($opt)" 1619 puts $fo "set cvscfg($opt) $cvscfg($opt)" 1620 set idx [lsearch $BOOLset $opt] 1621 set BOOLset [lreplace $BOOLset $idx $idx] 1622 set match 1 1623 break 1624 } 1625 } 1626 if {[string match "*set *cvscfg(checkrecursive)*" $line]} { 1627 # This helps us recover from a problem left behind by tkcvs 7.2 1628 continue 1629 } 1630 foreach opt $STRGopts { 1631 if {! [info exists cvscfg($opt)]} { continue } 1632 if {[string match "*set *cvscfg($opt)*" $line]} { 1633 # Print it and remove it from the list 1634 gen_log:log D "REPLACING $line w/ set cvscfg($opt) $cvscfg($opt)" 1635 puts $fo "set cvscfg($opt) \"$cvscfg($opt)\"" 1636 set idx [lsearch $STRGset $opt] 1637 set STRGset [lreplace $STRGset $idx $idx] 1638 set match 1 1639 break 1640 } 1641 } 1642 if {[string match "*set *cvscfg(editorargs)*" $line]} { 1643 # editorargs is no longer necessary 1644 continue 1645 } 1646 foreach opt $LOGopts { 1647 if {! [info exists logcfg($opt)]} { continue } 1648 if {[string match "*set *logcfg($opt)*" $line]} { 1649 # Print it and remove it from the list 1650 gen_log:log D "REPLACING \"$line\" w/ set logcfg($opt) \"$logcfg($opt)\"" 1651 puts $fo "set logcfg($opt) \"$logcfg($opt)\"" 1652 set idx [lsearch $LOGset $opt] 1653 set LOGset [lreplace $LOGset $idx $idx] 1654 set match 1 1655 break 1656 } 1657 } 1658 if {$match == 0} { 1659 # We didn't do a replacement 1660 gen_log:log D "PASSING \"$line\"" 1661 # If we don't check this, we get an extra blank line every time 1662 # we save the file. Messy. 1663 if {[eof $fi] == 1} { break } 1664 puts $fo "$line" 1665 } 1666 } 1667 } 1668 foreach mark [lsort [array names bookmarks]] { 1669 gen_log:log D "Adding bookmark \"$mark\"" 1670 puts $fo "set \"bookmarks($mark)\" \"$bookmarks($mark)\"" 1671 } 1672 1673 close $fi 1674 } 1675 1676 # Print what's left over 1677 foreach opt $BOOLset { 1678 if {! [info exists cvscfg($opt)]} { continue } 1679 gen_log:log D "ADDING cvscfg($opt) $cvscfg($opt)" 1680 puts $fo "set cvscfg($opt) $cvscfg($opt)" 1681 } 1682 1683 foreach opt $STRGset { 1684 if {! [info exists cvscfg($opt)]} { continue } 1685 gen_log:log D "ADDING cvscfg($opt) \"$cvscfg($opt)\"" 1686 puts $fo "set cvscfg($opt) \"$cvscfg($opt)\"" 1687 } 1688 1689 foreach opt $LOGset { 1690 if {! [info exists logcfg($opt)]} { continue } 1691 gen_log:log D "ADDING logcfg($opt) \"$logcfg($opt)\"" 1692 puts $fo "set logcfg($opt) \"$logcfg($opt)\"" 1693 } 1694 1695 close $fo 1696 ::picklist::save 1697 gen_log:log T "LEAVE" 1698} 1699 1700