3 # GUI interface for common LilyPond git repository commands
4 # Copyright 2009 by Johannes Schindelin and Carl Sorensen
9 # set to 1 to set up for translation, to 0 for other
12 if {$translator == 1} {
14 "LilyPond Translator's Git Interface version $version"
15 set updateButtonText "1. Update translation"
16 set initializeButtonText "1. Get translation"
17 set originHead "lilypond/translation"
21 "LilyPond Contributor's Git Interface version $version"
22 set updateButtonText "1. Update source"
23 set initializeButtonText "1. Get source"
24 set originHead "master"
30 ## Entry limit routine from jeff at hobbs org, downloaded from
31 ## http://www.purl.org/net/hobbs/tcl/tclet/entrylimit.html
33 ## For those who aren't using Tk4 with these, make a bell noop:
34 if [string match {} [info commands bell]] { proc bell args {} }
36 proc forceLen {len name el op} {
37 global $name ${name}_len
38 if [string comp $el {}] {
39 set old ${name}_len\($el)
41 } else { set old ${name}_len }
42 if {[string length [set $name]] > $len} {
49 ## entryLimit - a convenience proc for managing traces on entry widgets
50 ## Perhaps to make this even nicer, it could create a textvar for the
51 ## user with the name the same as the entry?
52 # ARGS: entry - the entry widget to trace
53 # traceProc - trace procedure
54 # init - initial value to use, defaults to {}
55 ## If traceProc=={}, then all write traces on the entry's textvar are
56 ## deleted. This doesn't delete array traces.
58 proc entryLimit {entry traceProc {init {}}} {
59 if [string match {} [set var [$entry cget -textvariable]]] {
60 return -code error "-textvariable not set for entry \"$entry\""
63 if {[string compare $traceProc {}]} {
64 ## TextVars are always considered global
65 uplevel \#0 [list set $var $init]
66 uplevel \#0 [list trace variable $var w $traceProc]
67 if {[catch {uplevel \#0 [list set $var $init]} err]} {
68 ## If this errors out, the $init value was bad, or
69 ## something was wrong with the traceProc
70 return -code error "an error was received setting the initial\
71 value of \"$var\" to \"$init\". Make sure the value is\
72 valid and the traceProc is functional:\n$err"
74 ## Do you really want to delete the trace when
75 ## destroying the entry?
76 #bind $entry <Destroy> [list + trace vdelete $var w $traceProc]
80 foreach p [uplevel \#0 [list trace vinfo $var]] {
81 if {[string match w [lindex $p 0]]} {
82 uplevel \#0 trace vdelete [list $var] $p
88 trace variable commit_header w {forceLen 50}
92 ## End of entry limit code
97 set lily_dir $env(HOME)/lilypond-git
98 if {[file exists $lily_dir]} {
102 set abort_dir "./aborted_edits"
104 proc write_to_output {s} {
105 .output.text insert insert $s
109 proc write_file_to_output {f} {
112 fconfigure $f -blocking true
113 if {[catch {close $f} err]} {
114 tk_messageBox -type ok -message \
115 "Command returned an error: $err\n\nCheck output text for details"
119 write_to_output [read $f 24]
124 global lily_dir git_command
125 set git_command [linsert $args 0 "|git" "--git-dir=$lily_dir/.git"]
126 set git_command "$git_command 2>@1"
127 .output.text insert end "$git_command\n"
128 set git [open $git_command r]
129 fconfigure $git -blocking false
130 fileevent $git readable [list write_file_to_output $git]
136 set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r]
137 set result [regsub "\n\$" [read $p] ""]
138 if {[catch {close $p} err]} {
139 tk_messageBox -type ok -message "config failed: $err"
144 proc config_quiet {args} {
146 set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r]
147 set result [regsub "\n\$" [read $p] ""]
148 if {[catch {close $p} err]} {
154 proc update_lilypond_rebase {} {
159 global commit_message
160 global commit_canceled
161 set commit_canceled 0
163 tkwait visibility .commitMessage
164 tkwait window .commitMessage
165 if {$commit_canceled != 1} {
166 if {$commit_message == ""} {
167 tk_messageBox -message "You must enter a commit message!" \
170 git commit -a -m $commit_message
171 git rebase --whitespace=fix HEAD^
172 set commit_message "2
177 proc commit_amend {} {
178 git commit -a --amend -C HEAD
179 git rebase --whitespace=fix HEAD^
182 proc update_lilypond_norebase {} {
186 proc update_lilypond_with_rebase {} {
188 update_lilypond $rebase
191 proc update_lilypond {rebase} {
195 . config -cursor watch
196 if {![file exists $lily_dir]} {
197 write_to_output "Cloning LilyPond (this can take some time) ...\n"
201 git config core.bare false
202 git remote add -t $originHead \
203 origin git://git.sv.gnu.org/lilypond.git
204 if {$translator == 1} {
209 git reset --hard origin/$originHead
210 git config branch.$originHead.remote origin
211 git config branch.$originHead.merge refs/heads/$originHead
212 .buttons.commitFrame.commit configure -state normal
213 .buttons.commitFrame.amend configure -state normal
214 .buttons.update configure -text buttonUpdateText
215 .buttons.patch configure -state normal
216 .buttons.panic configure -state normal
219 write_to_output "Updating LilyPond...\n"
222 git rebase origin/$originHead
224 git merge origin/$originHead
227 write_to_output "Done.\n"
231 proc patch_from_origin {} {
233 make_patch_from_origin $rebase
234 if {![llength [glob -nocomplain 0*.patch]]} {
235 tk_messageBox -type ok -message \
236 "No patches created; did you make a local commit?"
240 proc make_patch_from_origin {rebase} {
243 . config -cursor watch
244 update_lilypond $rebase
245 write_to_output "Creating patch...\n"
246 git format-patch origin/$originHead
247 write_to_output "Done.\n"
251 proc abort_changes {} {
254 set answer [tk_messageBox -type okcancel \
255 -message "This will copy all changed files to $abort_dir and reset the repository." \
259 write_to_output "abort_dir: $abort_dir \n"
260 if {![file exists $abort_dir]} {
261 set return_code [exec mkdir $abort_dir]
263 set return_code [catch {exec git diff origin/$originHead} gitdiff]
264 set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file]
265 while {$return_code != 0} {
266 write_to_output "Copying $modified_file to $abort_dir.\n"
267 set return_code [catch {exec cp $modified_file $abort_dir} result]
268 set return_code [regsub {diff --git a/(\S*)} $gitdiff "" gitdiff]
269 set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file]
271 set return_code [git reset --hard origin/$originHead]
272 write_to_output "Repository reset. \n"
277 proc toggle_rebase {} {
281 global updateButtonText
282 global initializeButtonText
283 if {[file exists $lily_dir]} {
284 config --bool branch.$originHead.rebase $rebase
285 .buttons.update configure -text $updateButtonText
287 .buttons.update configure -text $initializeButtonText
291 proc clear_rebase {} {
303 proc commitMessageOK {} {
304 global commit_message
306 set commit_body [.commitMessage.bottomFrame.commit_body get 1.0 end]
307 set commit_message "$commit_header\n\n$commit_body"
308 destroy .commitMessage
311 proc commitMessageCancel {} {
312 global commit_message
313 global commit_canceled
314 set commit_message ""
315 set commit_canceled 1
316 destroy .commitMessage
320 # Commit message input window
321 proc get_commit_message {} {
324 toplevel .commitMessage
325 frame .commitMessage.topFrame
326 label .commitMessage.topFrame.label \
327 -text "Enter commit message header:\n(50 chars max = width of box)"
328 entry .commitMessage.topFrame.commit_header \
329 -width 50 -relief solid -border 2 -textvariable commit_header
330 pack .commitMessage.topFrame.label -side left
331 pack .commitMessage.topFrame.commit_header -side left
333 frame .commitMessage.bottomFrame
334 text .commitMessage.bottomFrame.commit_body \
335 -width 75 -height 10 -relief solid -border 2 -wrap none
337 frame .commitMessage.bottomFrame.leftFrame
338 label .commitMessage.bottomFrame.leftFrame.label \
339 -text "Enter commit message body:\n(No limit -- Full description)"
340 button .commitMessage.bottomFrame.leftFrame.ok \
341 -text OK -default active -command commitMessageOK
342 button .commitMessage.bottomFrame.leftFrame.cancel -text Cancel -default active \
343 -command commitMessageCancel
344 wm withdraw .commitMessage
345 wm title .commitMessage "Git Commit Message"
347 pack .commitMessage.bottomFrame.leftFrame.label
348 pack .commitMessage.bottomFrame.leftFrame.ok
349 pack .commitMessage.bottomFrame.leftFrame.cancel
351 pack .commitMessage.bottomFrame.leftFrame -side left
352 pack .commitMessage.bottomFrame.commit_body -side left
354 pack .commitMessage.topFrame
355 pack .commitMessage.bottomFrame
357 wm transient .commitMessage .
358 wm deiconify .commitMessage
364 wm title . $windowTitle
370 frame .buttons.commitFrame
371 button .buttons.commitFrame.commit -text "2a. New local commit" -command commit
372 button .buttons.commitFrame.amend -text "2b. Amend previous commit" -command commit_amend
373 pack .buttons.commitFrame.commit -fill x
374 pack .buttons.commitFrame.amend -fill x
376 button .buttons.update -text $updateButtonText \
377 -command update_lilypond_with_rebase
378 button .buttons.patch -text "3. Make patch set" \
379 -command patch_from_origin
381 button .buttons.panic -text "Abort changes -- Reset to origin" \
382 -command abort_changes -fg Blue -bg Red
383 label .buttons.spacer -text " "
384 if {![file exists $lily_dir]} {
385 .buttons.update configure \
386 -text $initializeButtonText
387 .buttons.commitFrame.commit configure -state disabled
388 .buttons.commitFrame.amend configure -state disabled
389 .buttons.patch configure -state disabled
390 .buttons.panic configure -state disabled
395 pack .buttons.update -side left
396 pack .buttons.commitFrame -side left
397 pack .buttons.patch -side left
398 pack .buttons.spacer -side left
399 pack .buttons.panic -side right
405 label .output.label -text "Command output:"
406 text .output.text -width 80 -height 15 \
407 -xscrollcommand [list .output.horizontal set] \
408 -yscrollcommand [list .output.vertical set] \
409 -relief solid -border 2
410 scrollbar .output.horizontal -orient h -command [list .output.text xview]
411 scrollbar .output.vertical -orient v -command [list .output.text yview]
412 pack .output.label -side left
413 pack .output.horizontal -side bottom -fill x
414 pack .output.vertical -side right -fill y
415 pack .output.text -expand true -anchor nw -fill both
420 #grid .buttons -row 2 -column 1
421 #grid .output -row 3 -column 1 -sticky "w"