3 # GUI interface for common LilyPond git repository commands
4 # Copyright 2009--2010 by Johannes Schindelin and Carl Sorensen
9 # set to 1 to set up for translation, to 0 for other
12 # location of lilypond git
13 set lily_dir $env(HOME)/lilypond-git
16 if {$translator == 1} {
18 "LilyPond Translator's Git Interface version $version"
19 set updateButtonText "1. Update translation"
20 set initializeButtonText "1. Get translation"
21 set originHead "lilypond/translation"
25 "LilyPond Contributor's Git Interface version $version"
26 set updateButtonText "1. Update source"
27 set initializeButtonText "1. Get source"
28 set originHead "master"
34 ## Entry limit routine from jeff at hobbs org, downloaded from
35 ## http://www.purl.org/net/hobbs/tcl/tclet/entrylimit.html
37 ## For those who aren't using Tk4 with these, make a bell noop:
38 if [string match {} [info commands bell]] { proc bell args {} }
40 proc forceLen {len name el op} {
41 global $name ${name}_len
42 if [string comp $el {}] {
43 set old ${name}_len\($el)
45 } else { set old ${name}_len }
46 if {[string length [set $name]] > $len} {
53 ## Here is a wish example to use the routines. Remember that with
54 ## write traces, a valid value must be set for each variable both
55 ## before AND after the trace is established.
59 ## 1) textvariable specification
64 trace variable commit_header w {forceLen 50}
68 ## End of entry limit code
73 if {[file exists $lily_dir]} {
77 set abort_dir "./aborted_edits"
79 proc write_to_output {s} {
80 .output.text insert insert $s
84 proc write_file_to_output {f} {
87 fconfigure $f -blocking true
88 if {[catch {close $f} err]} {
89 tk_messageBox -type ok -message \
90 "Command returned an error: $err\n\nCheck output text for details"
94 write_to_output [read $f 24]
99 global lily_dir git_command
100 set git_command [linsert $args 0 "|git" "--git-dir=$lily_dir/.git"]
101 set git_command "$git_command 2>@1"
102 .output.text insert end "$git_command\n"
103 set git [open $git_command r]
104 fconfigure $git -blocking false
105 fileevent $git readable [list write_file_to_output $git]
111 set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r]
112 set result [regsub "\n\$" [read $p] ""]
113 if {[catch {close $p} err]} {
114 tk_messageBox -type ok -message "config failed: $err"
119 proc config_quiet {args} {
121 set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r]
122 set result [regsub "\n\$" [read $p] ""]
123 if {[catch {close $p} err]} {
129 proc update_lilypond_rebase {} {
134 global commit_message
135 global commit_canceled
136 set commit_canceled 0
138 tkwait visibility .commitMessage
139 tkwait window .commitMessage
140 if {$commit_canceled != 1} {
141 if {$commit_message == ""} {
142 tk_messageBox -message "You must enter a commit message!" \
145 git commit -a -m $commit_message
146 git rebase --whitespace=fix HEAD^
147 set commit_message ""
152 proc commit_amend {} {
153 git commit -a --amend -C HEAD
154 git rebase --whitespace=fix HEAD^
157 proc update_lilypond_norebase {} {
161 proc update_lilypond_with_rebase {} {
163 update_lilypond $rebase
166 proc update_lilypond {rebase} {
170 . config -cursor watch
171 if {![file exists $lily_dir]} {
172 write_to_output "Cloning LilyPond (this can take some time) ...\n"
176 git config core.bare false
177 git remote add -t $originHead \
178 origin git://git.sv.gnu.org/lilypond.git
179 if {$translator == 1} {
184 git reset --hard origin/$originHead
185 git config branch.$originHead.remote origin
186 git config branch.$originHead.merge refs/heads/$originHead
187 .buttons.commitFrame.commit configure -state normal
188 .buttons.commitFrame.amend configure -state normal
189 .buttons.update configure -text buttonUpdateText
190 .buttons.patch configure -state normal
191 .buttons.panic configure -state normal
194 write_to_output "Updating LilyPond...\n"
197 git rebase origin/$originHead
199 git merge origin/$originHead
202 write_to_output "Done.\n"
206 proc patch_from_origin {} {
208 make_patch_from_origin $rebase
209 if {![llength [glob -nocomplain 0*.patch]]} {
210 tk_messageBox -type ok -message \
211 "No patches created; did you make a local commit?"
215 proc make_patch_from_origin {rebase} {
218 . config -cursor watch
219 update_lilypond $rebase
220 write_to_output "Creating patch...\n"
221 git format-patch origin/$originHead
222 write_to_output "Done.\n"
226 proc abort_changes {} {
229 set answer [tk_messageBox -type okcancel \
230 -message "This will copy all changed files to $abort_dir and reset the repository." \
234 write_to_output "abort_dir: $abort_dir \n"
235 if {![file exists $abort_dir]} {
236 set return_code [exec mkdir $abort_dir]
238 set return_code [catch {exec git diff origin/$originHead} gitdiff]
239 set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file]
240 while {$return_code != 0} {
241 write_to_output "Copying $modified_file to $abort_dir.\n"
242 set return_code [catch {exec cp $modified_file $abort_dir} result]
243 set return_code [regsub {diff --git a/(\S*)} $gitdiff "" gitdiff]
244 set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file]
246 set return_code [git reset --hard origin/$originHead]
247 write_to_output "Repository reset. \n"
252 proc toggle_rebase {} {
256 global updateButtonText
257 global initializeButtonText
258 if {[file exists $lily_dir]} {
259 config --bool branch.$originHead.rebase $rebase
260 .buttons.update configure -text $updateButtonText
262 .buttons.update configure -text $initializeButtonText
266 proc clear_rebase {} {
278 proc commitMessageOK {} {
279 global commit_message
281 set commit_body [.commitMessage.bottomFrame.commit_body get 1.0 end]
282 set commit_message "$commit_header\n\n$commit_body"
283 destroy .commitMessage
286 proc commitMessageCancel {} {
287 global commit_message
288 global commit_canceled
289 set commit_message ""
290 set commit_canceled 1
291 destroy .commitMessage
295 # Commit message input window
296 proc get_commit_message {} {
299 toplevel .commitMessage
300 frame .commitMessage.topFrame
301 label .commitMessage.topFrame.label \
302 -text "Enter commit message header:\n(50 chars max = width of box)"
303 entry .commitMessage.topFrame.commit_header \
304 -width 50 -relief solid -border 2 -textvariable commit_header
305 pack .commitMessage.topFrame.label -side left
306 pack .commitMessage.topFrame.commit_header -side left
308 frame .commitMessage.bottomFrame
309 text .commitMessage.bottomFrame.commit_body \
310 -width 75 -height 10 -relief solid -border 2 -wrap none
312 frame .commitMessage.bottomFrame.leftFrame
313 label .commitMessage.bottomFrame.leftFrame.label \
314 -text "Enter commit message body:\n(No limit -- Full description)"
315 button .commitMessage.bottomFrame.leftFrame.ok \
316 -text OK -default active -command commitMessageOK
317 button .commitMessage.bottomFrame.leftFrame.cancel -text Cancel -default active \
318 -command commitMessageCancel
319 wm withdraw .commitMessage
320 wm title .commitMessage "Git Commit Message"
322 pack .commitMessage.bottomFrame.leftFrame.label
323 pack .commitMessage.bottomFrame.leftFrame.ok
324 pack .commitMessage.bottomFrame.leftFrame.cancel
326 pack .commitMessage.bottomFrame.leftFrame -side left
327 pack .commitMessage.bottomFrame.commit_body -side left
329 pack .commitMessage.topFrame
330 pack .commitMessage.bottomFrame
332 wm transient .commitMessage .
333 wm deiconify .commitMessage
339 wm title . $windowTitle
345 frame .buttons.commitFrame
346 button .buttons.commitFrame.commit -text "2a. New local commit" -command commit
347 button .buttons.commitFrame.amend -text "2b. Amend previous commit" -command commit_amend
348 pack .buttons.commitFrame.commit -fill x
349 pack .buttons.commitFrame.amend -fill x
351 button .buttons.update -text $updateButtonText \
352 -command update_lilypond_with_rebase
353 button .buttons.patch -text "3. Make patch set" \
354 -command patch_from_origin
356 button .buttons.panic -text "Abort changes -- Reset to origin" \
357 -command abort_changes -fg Blue -bg Red
358 label .buttons.spacer -text " "
359 if {![file exists $lily_dir]} {
360 .buttons.update configure \
361 -text $initializeButtonText
362 .buttons.commitFrame.commit configure -state disabled
363 .buttons.commitFrame.amend configure -state disabled
364 .buttons.patch configure -state disabled
365 .buttons.panic configure -state disabled
370 pack .buttons.update -side left
371 pack .buttons.commitFrame -side left
372 pack .buttons.patch -side left
373 pack .buttons.spacer -side left
374 pack .buttons.panic -side right
380 label .output.label -text "Command output:"
381 text .output.text -width 80 -height 15 \
382 -xscrollcommand [list .output.horizontal set] \
383 -yscrollcommand [list .output.vertical set] \
384 -relief solid -border 2
385 scrollbar .output.horizontal -orient h -command [list .output.text xview]
386 scrollbar .output.vertical -orient v -command [list .output.text yview]
387 pack .output.label -side left
388 pack .output.horizontal -side bottom -fill x
389 pack .output.vertical -side right -fill y
390 pack .output.text -expand true -anchor nw -fill both
395 #grid .buttons -row 2 -column 1
396 #grid .output -row 3 -column 1 -sticky "w"