]> git.donarmstrong.com Git - lilypond.git/blob - scripts/auxiliar/lily-git.tcl
lily-git.tcl: Change repo directory to lilypond-git
[lilypond.git] / scripts / auxiliar / lily-git.tcl
1 #!/usr/bin/wish
2
3 # GUI interface for common LilyPond git repository commands
4 # Copyright 2009 by Johannes Schindelin and Carl Sorensen
5 #
6
7 set version 0.60
8
9 # set to 1 to set up for translation, to 0 for other
10 set translator 0
11
12 if {$translator == 1} {
13         set windowTitle \
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"
18         set rebase 0
19 } else {
20         set windowTitle \
21           "LilyPond Contributor's Git Interface version $version"
22         set updateButtonText "1. Update source"
23         set initializeButtonText "1. Get source"
24         set originHead "master"
25         set rebase 1
26 }
27 package require Tk
28
29 # Helper functions
30
31 set lily_dir $env(HOME)/lilypond-git
32 if {[file exists $lily_dir]} {
33         cd $lily_dir
34 }
35
36 set abort_dir "./aborted_edits"
37
38 proc write_to_output {s} {
39         .output.text insert insert $s
40         .output.text see end
41 }
42
43 proc write_file_to_output {f} {
44         if {[eof $f]} {
45                 global git_command
46                 fconfigure $f -blocking true
47                 if {[catch {close $f} err]} {
48                         tk_messageBox -type ok -message \
49                           "Command returned an error: $err\n\nCheck output text for details"
50                 }
51                 unset git_command
52         } else {
53                 write_to_output [read $f 24]
54         }
55 }
56
57 proc git {args} {
58         global lily_dir git_command
59         set git_command [linsert $args 0 "|git" "--git-dir=$lily_dir/.git"]
60         set git_command "$git_command 2>@1"
61         .output.text insert end "$git_command\n"
62         set git [open $git_command r]
63         fconfigure $git -blocking false
64         fileevent $git readable [list write_file_to_output $git]
65         vwait git_command
66 }
67
68 proc config {args} {
69         global lily_dir
70         set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r]
71         set result [regsub "\n\$" [read $p] ""]
72         if {[catch {close $p} err]} {
73                 tk_messageBox -type ok -message "config failed: $err"
74         }
75         return $result
76 }
77
78 proc config_quiet {args} {
79         global lily_dir
80         set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r]
81         set result [regsub "\n\$" [read $p] ""]
82         if {[catch {close $p} err]} {
83                 set result ""
84         }
85         return $result
86 }
87
88 proc update_lilypond_rebase {} {
89   update_lilypond 1
90 }
91
92 proc commit {} {
93   global commit_message
94   global commit_canceled
95   set commit_canceled 0
96   get_commit_message
97   tkwait visibility .commitMessage
98   tkwait window .commitMessage
99   if {$commit_canceled != 1} {
100     if {$commit_message == ""} {
101       tk_messageBox -message "You must enter a commit message!" \
102       -type ok -icon error
103     } else {
104       git commit -a -m $commit_message
105       git rebase --whitespace=fix HEAD^
106     set commit_message ""
107     }
108   }
109 }
110
111 # This won't work, because --amend needs an editor
112 #  lilyconfig users are on their own.
113 proc commit_amend {} {
114   git commit -a --amend
115   git rebase --whitespace=fix HEAD^
116 }
117
118 proc update_lilypond_norebase {} {
119   update_lilypond 0
120 }
121
122 proc update_lilypond_with_rebase {} {
123   global rebase
124   update_lilypond $rebase
125 }
126
127 proc update_lilypond {rebase} {
128         global lily_dir
129         global originHead
130         global translator
131         . config -cursor watch
132         if {![file exists $lily_dir]} {
133                 write_to_output "Cloning LilyPond (this can take some time) ...\n"
134                 file mkdir $lily_dir
135                 cd $lily_dir
136                 git init
137                 git config core.bare false
138                 git remote add -t $originHead \
139                         origin git://git.sv.gnu.org/lilypond.git
140                 if {$translator == 1} {
141                   git fetch
142                 } else {
143                   git fetch --depth 1
144                 }
145                 git reset --hard origin/$originHead
146                 git config branch.$originHead.remote origin
147                 git config branch.$originHead.merge refs/heads/$originHead
148                 .buttons.commit configure -state normal
149                 .buttons.update configure -text buttonUpdateText
150                 .buttons.patch configure -state normal
151                 .buttons.panic configure -state normal
152                 toggle_rebase
153         } else {
154                 write_to_output "Updating LilyPond...\n"
155                 git fetch origin
156                 if {$rebase} {
157                         git rebase origin/$originHead
158                 } else {
159                         git merge origin/$originHead
160                 }
161         }
162         write_to_output "Done.\n"
163         . config -cursor ""
164 }
165
166 proc patch_from_origin {} {
167   global rebase
168   make_patch_from_origin $rebase
169   if {![llength [glob -nocomplain 0*.patch]]} {
170         tk_messageBox -type ok -message \
171                 "No patches created; did you make a local commit?"
172   }
173 }
174
175 proc make_patch_from_origin {rebase} {
176   global lily_dir
177   global originHead
178   . config -cursor watch
179   update_lilypond $rebase
180   write_to_output "Creating patch...\n"
181   git format-patch origin/$originHead
182   write_to_output "Done.\n"
183   . config -cursor ""
184 }
185
186 proc abort_changes {} {
187   global abort_dir
188   global originHead
189   set answer [tk_messageBox -type okcancel \
190                -message "This will copy all changed files to $abort_dir and reset the repository." \
191                -default cancel]
192   switch -- $answer {
193     ok {
194       write_to_output "abort_dir: $abort_dir \n"
195       if {![file exists $abort_dir]} {
196         set return_code [exec mkdir $abort_dir]
197       }
198       set return_code [catch {exec git diff origin/$originHead} gitdiff]
199       set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file]
200       while {$return_code != 0} {
201         write_to_output "Copying $modified_file to $abort_dir.\n"
202         set return_code [catch {exec cp $modified_file $abort_dir} result]
203         set return_code [regsub {diff --git a/(\S*)} $gitdiff "" gitdiff]
204         set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file]
205       }
206       set return_code [git reset --hard origin/$originHead]
207       write_to_output "Repository reset. \n"
208     }
209   }
210 }
211
212 proc toggle_rebase {} {
213         global rebase
214         global lily_dir
215         global originHead
216         global updateButtonText
217         global initializeButtonText
218         if {[file exists $lily_dir]} {
219           config --bool branch.$originHead.rebase $rebase
220           .buttons.update configure -text $updateButtonText
221         } else {
222           .buttons.update configure -text $initializeButtonText
223         }
224 }
225
226 proc clear_rebase {} {
227   global rebase
228   set rebase 0
229   toggle_rebase
230 }
231
232 proc set_rebase {} {
233   global rebase
234   set rebase 1
235   toggle_rebase
236 }
237
238 proc commitMessageOK {} {
239   global commit_message
240   global commit_header
241   set commit_body [.commitMessage.bottomFrame.commit_body get 1.0 end]
242   set commit_message "$commit_header\n\n$commit_body"
243   destroy .commitMessage
244 }
245
246 proc commitMessageCancel {} {
247   global commit_message
248   global commit_canceled
249   set commit_message ""
250   set commit_canceled 1
251   destroy .commitMessage
252 }
253
254
255 # Commit message input window
256 proc get_commit_message {} {
257   global commit_header
258   set commit_header ""
259   toplevel .commitMessage
260   frame .commitMessage.topFrame
261   label .commitMessage.topFrame.label \
262       -text "Enter commit message header:\n(50 chars max = width of box)"
263   entry .commitMessage.topFrame.commit_header \
264             -width 50 -relief solid -border 2 -textvariable commit_header
265   pack   .commitMessage.topFrame.label -side left
266   pack   .commitMessage.topFrame.commit_header -side left
267
268   frame  .commitMessage.bottomFrame
269   text   .commitMessage.bottomFrame.commit_body \
270             -width 75  -height 10 -relief solid -border 2 -wrap none
271
272   frame .commitMessage.bottomFrame.leftFrame
273   label .commitMessage.bottomFrame.leftFrame.label \
274       -text "Enter commit message body:\n(No limit -- Full description)"
275   button .commitMessage.bottomFrame.leftFrame.ok \
276            -text OK -default active -command commitMessageOK
277   button .commitMessage.bottomFrame.leftFrame.cancel -text Cancel -default active \
278           -command commitMessageCancel
279   wm withdraw .commitMessage
280   wm title .commitMessage "Git Commit Message"
281
282   pack .commitMessage.bottomFrame.leftFrame.label
283   pack .commitMessage.bottomFrame.leftFrame.ok
284   pack .commitMessage.bottomFrame.leftFrame.cancel
285
286   pack .commitMessage.bottomFrame.leftFrame -side left
287   pack .commitMessage.bottomFrame.commit_body -side left
288
289   pack .commitMessage.topFrame
290   pack .commitMessage.bottomFrame
291
292   wm transient .commitMessage .
293   wm deiconify .commitMessage
294 }
295
296
297 # GUI
298
299 wm title . $windowTitle
300
301 # Buttons
302
303 panedwindow .buttons
304 button .buttons.commit -text "2. Make local commit" -command commit
305 button .buttons.update -text $updateButtonText \
306           -command update_lilypond_with_rebase
307 toggle_rebase
308 button .buttons.patch -text "3. Make patch set" \
309           -command patch_from_origin
310 button .buttons.panic -text "Abort changes -- Reset to origin" \
311           -command abort_changes -fg Blue -bg Red
312 label   .buttons.spacer -text "                         "
313 if {![file exists $lily_dir]} {
314         .buttons.update configure \
315             -text $initializeButtonText
316         .buttons.commit configure -state disabled
317         .buttons.patch configure -state disabled
318         .buttons.panic configure -state disabled
319 }
320
321 #  Operating buttons
322
323 pack .buttons.update -side left
324 pack .buttons.commit -side left
325 pack .buttons.patch -side left
326 pack .buttons.spacer -side left
327 pack .buttons.panic -side left
328
329
330 # Output text box
331
332 panedwindow .output
333 label .output.label -text "Command output:"
334 text .output.text -width 80 -height 15 \
335         -xscrollcommand [list .output.horizontal set] \
336         -yscrollcommand [list .output.vertical set] \
337         -relief solid -border 2
338 scrollbar .output.horizontal -orient h -command [list .output.text xview]
339 scrollbar .output.vertical -orient v -command [list .output.text yview]
340 pack .output.label -side left
341 pack .output.horizontal -side bottom -fill x
342 pack .output.vertical -side right -fill y
343 pack .output.text -expand true -anchor nw -fill both
344
345 pack .buttons
346 pack .output
347
348 #grid .buttons -row 2 -column 1
349 #grid .output -row 3 -column 1 -sticky "w"