X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fauxiliar%2Flily-git.tcl;fp=scripts%2Fauxiliar%2Flily-git.tcl;h=6f16791313d94a5aa83bfe7742406c16fff93e37;hb=941dff9d2a67080e0dd8474f1e70f0c72ace6424;hp=0000000000000000000000000000000000000000;hpb=5a22d6233a39d3164e1ca043244794c268be4ad0;p=lilypond.git diff --git a/scripts/auxiliar/lily-git.tcl b/scripts/auxiliar/lily-git.tcl new file mode 100755 index 0000000000..6f16791313 --- /dev/null +++ b/scripts/auxiliar/lily-git.tcl @@ -0,0 +1,440 @@ +#!/usr/bin/wish + +# GUI interface for common LilyPond git repository commands +# Copyright 2009--2011 by Johannes Schindelin and Carl Sorensen +# + +set version 0.64 + +# set to 1 to set up for translation, to 0 for other +set translator 0 + +# location of lilypond git +set lily_dir $env(HOME)/lilypond-git + +if {$translator == 1} { + set windowTitle \ + "LilyPond Translator's Git Interface version $version" + set updateButtonText "1. Update translation" + set initializeButtonText "1. Get translation" + set originHead "lilypond/translation" + set rebase 0 +} else { + set windowTitle \ + "LilyPond Contributor's Git Interface version $version" + set updateButtonText "1. Update source" + set initializeButtonText "1. Get source" + set originHead "master" + set rebase 1 +} +package require Tk + +## Submits the user data collected using the git config command + +proc submituserdata {} { + exec git config --global user.name "$::username" + exec git config --global user.email "$::useremail" + destroy .b + return 0 +} + +## Request name and email from user + +proc requestuserdata {} { + toplevel .b + grab .b + wm geometry .b -300-300 + wm title .b "Contributor details" + grid [frame .b.c ] -column 0 -row 0 -sticky nwes + grid columnconfigure . 0 -weight 1; grid rowconfigure . 0 -weight 1 + + grid [entry .b.c.username -width 20 -textvariable username] -column 2 -row 2 -sticky we + grid [entry .b.c.useremail -width 20 -textvariable useremail] -column 2 -row 3 -sticky we + grid [button .b.c.submituserdata -text "Submit" -command submituserdata] -column 2 -row 4 + + grid [label .b.c.explbl -text "Please enter your name and email for future commits:"] -column 1 -row 1 -columnspan 3 -sticky we + grid [label .b.c.nmlbl -text "Name:"] -column 1 -row 2 -sticky w + grid [label .b.c.emlbl -text "Email:"] -column 1 -row 3 -sticky w + + foreach w [winfo children .b.c] {grid configure $w -padx 5 -pady 5} + focus .b.c.username + bind .b {submituserdata} +} + +## Checks the user's global .gitconfig for name and email and executes requestuserdata if either is not found + +if {![file exists "$env(HOME)/.gitconfig"]} { + set fileholder [open "$env(HOME)/.gitconfig" a+] +} else { + set fileholder [open "$env(HOME)/.gitconfig" r] +} + +set usercheck [split [read $fileholder] "\n"] +close $fileholder +if {![regexp "name" $usercheck] || ![regexp "email" $usercheck]} then { + requestuserdata + tkwait window .b +} + +## Entry limit routine from jeff at hobbs org, downloaded from +## http://www.purl.org/net/hobbs/tcl/tclet/entrylimit.html + +## For those who aren't using Tk4 with these, make a bell noop: +if [string match {} [info commands bell]] { proc bell args {} } + +proc forceLen {len name el op} { + global $name ${name}_len + if [string comp $el {}] { + set old ${name}_len\($el) + set name $name\($el) + } else { + set old ${name}_len + } + if {[string length [set $name]] > $len} { + set $name [set $old] + bell; + return + } + set $old [set $name] +} + +## Here is a wish example to use the routines. Remember that with +## write traces, a valid value must be set for each variable both +## before AND after the trace is established. + +## The order must be: +## 1) variable init +## 1) textvariable specification +## 3) set trace +## 4) variable reinit + +set commit_header {} +trace variable commit_header w {forceLen 50} +set commit_header {} + + +## End of entry limit code + + +# Helper functions + +if {[file exists $lily_dir]} { + cd $lily_dir +} + +set abort_dir "./aborted_edits" + +proc write_to_output {s} { + .output.text insert insert $s + .output.text see end +} + +proc write_file_to_output {f} { + if {[eof $f]} { + global git_command + fconfigure $f -blocking true + if {[catch {close $f} err]} { + tk_messageBox -type ok -message \ + "Command returned an error: $err\n\nCheck output text for details" + } + unset git_command + } else { + write_to_output [read $f 24] + } +} + +proc git {args} { + global lily_dir git_command + set git_command [linsert $args 0 "|git" "--git-dir=$lily_dir/.git"] + set git_command "$git_command 2>@1" + .output.text insert end "$git_command\n" + set git [open $git_command r] + fconfigure $git -blocking false + fileevent $git readable [list write_file_to_output $git] + vwait git_command +} + +proc config {args} { + global lily_dir + set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r] + set result [regsub "\n\$" [read $p] ""] + if {[catch {close $p} err]} { + tk_messageBox -type ok -message "config failed: $err" + } + return $result +} + +proc config_quiet {args} { + global lily_dir + set p [open [linsert $args 0 "|git" --git-dir=$lily_dir/.git config] r] + set result [regsub "\n\$" [read $p] ""] + if {[catch {close $p} err]} { + set result "" + } + return $result +} + +proc update_lilypond_rebase {} { + update_lilypond 1 +} + +proc commit {} { + global commit_message + global commit_canceled + set commit_canceled 0 + get_commit_message + tkwait visibility .commitMessage + tkwait window .commitMessage + if {$commit_canceled != 1} { + if {$commit_message == ""} { + tk_messageBox -message "You must enter a commit message!" \ + -type ok -icon error + } else { + git commit -a -m $commit_message + git rebase --whitespace=fix HEAD^ + set commit_message "" + } + } +} + +proc commit_amend {} { + git commit -a --amend -C HEAD + git rebase --whitespace=fix HEAD^ +} + +proc update_lilypond_norebase {} { + update_lilypond 0 +} + +proc update_lilypond_with_rebase {} { + global rebase + update_lilypond $rebase +} + +proc update_lilypond {rebase} { + global lily_dir + global originHead + global translator + . config -cursor watch + if {![file exists $lily_dir]} { + write_to_output "Cloning LilyPond (this can take some time) ...\n" + file mkdir $lily_dir + cd $lily_dir + git init + git config core.bare false + git remote add -t $originHead \ + origin git://git.sv.gnu.org/lilypond.git + git fetch + git reset --hard origin/$originHead + git config branch.$originHead.remote origin + git config branch.$originHead.merge refs/heads/$originHead + .buttons.commitFrame.commit configure -state normal + .buttons.commitFrame.amend configure -state normal + .buttons.update configure -text buttonUpdateText + .buttons.patch configure -state normal + .buttons.panic configure -state normal + toggle_rebase + } else { + write_to_output "Updating LilyPond...\n" + git fetch origin + if {$rebase} { + git rebase origin/$originHead + } else { + git merge origin/$originHead + } + } + write_to_output "Done.\n" + . config -cursor "" +} + +proc patch_from_origin {} { + global rebase + make_patch_from_origin $rebase + if {![llength [glob -nocomplain 0*.patch]]} { + tk_messageBox -type ok -message \ + "No patches created; did you make a local commit?" + } +} + +proc make_patch_from_origin {rebase} { + global lily_dir + global originHead + . config -cursor watch + update_lilypond $rebase + write_to_output "Creating patch...\n" + git format-patch origin/$originHead + write_to_output "Done.\n" + . config -cursor "" +} + +proc abort_changes {} { + global abort_dir + global originHead + set answer [tk_messageBox -type okcancel \ + -message "This will copy all changed files to $abort_dir and reset the repository." \ + -default cancel] + switch -- $answer { + ok { + write_to_output "abort_dir: $abort_dir \n" + if {![file exists $abort_dir]} { + set return_code [exec mkdir $abort_dir] + } + set return_code [catch {exec git diff origin/$originHead} gitdiff] + set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file] + while {$return_code != 0} { + write_to_output "Copying $modified_file to $abort_dir.\n" + set return_code [catch {exec cp $modified_file $abort_dir} result] + set return_code [regsub {diff --git a/(\S*)} $gitdiff "" gitdiff] + set return_code [regexp {diff --git a/(\S*)} $gitdiff match modified_file] + } + set return_code [git reset --hard origin/$originHead] + write_to_output "Repository reset. \n" + } + } +} + +proc toggle_rebase {} { + global rebase + global lily_dir + global originHead + global updateButtonText + global initializeButtonText + if {[file exists $lily_dir]} { + config --bool branch.$originHead.rebase $rebase + .buttons.update configure -text $updateButtonText + } else { + .buttons.update configure -text $initializeButtonText + } +} + +proc clear_rebase {} { + global rebase + set rebase 0 + toggle_rebase +} + +proc set_rebase {} { + global rebase + set rebase 1 + toggle_rebase +} + +proc commitMessageOK {} { + global commit_message + global commit_header + set commit_body [.commitMessage.bottomFrame.commit_body get 1.0 end] + set commit_message "$commit_header\n\n$commit_body" + destroy .commitMessage +} + +proc commitMessageCancel {} { + global commit_message + global commit_canceled + set commit_message "" + set commit_canceled 1 + destroy .commitMessage +} + + +# Commit message input window +proc get_commit_message {} { + global commit_header + set commit_header "" + toplevel .commitMessage + frame .commitMessage.topFrame + label .commitMessage.topFrame.label \ + -text "Enter commit message header:\n(50 chars max = width of box)" + entry .commitMessage.topFrame.commit_header \ + -width 50 -relief solid -border 2 -textvariable commit_header + pack .commitMessage.topFrame.label -side left + pack .commitMessage.topFrame.commit_header -side left + + frame .commitMessage.bottomFrame + text .commitMessage.bottomFrame.commit_body \ + -width 75 -height 10 -relief solid -border 2 -wrap none + + frame .commitMessage.bottomFrame.leftFrame + label .commitMessage.bottomFrame.leftFrame.label \ + -text "Enter commit message body:\n(No limit -- Full description)" + button .commitMessage.bottomFrame.leftFrame.ok \ + -text OK -default active -command commitMessageOK + button .commitMessage.bottomFrame.leftFrame.cancel -text Cancel -default active \ + -command commitMessageCancel + wm withdraw .commitMessage + wm title .commitMessage "Git Commit Message" + + pack .commitMessage.bottomFrame.leftFrame.label + pack .commitMessage.bottomFrame.leftFrame.ok + pack .commitMessage.bottomFrame.leftFrame.cancel + + pack .commitMessage.bottomFrame.leftFrame -side left + pack .commitMessage.bottomFrame.commit_body -side left + + pack .commitMessage.topFrame + pack .commitMessage.bottomFrame + + wm transient .commitMessage . + wm deiconify .commitMessage +} + + +# GUI + +wm title . $windowTitle + +# Buttons + +panedwindow .buttons + +frame .buttons.commitFrame +button .buttons.commitFrame.commit -text "2a. New local commit" -command commit +button .buttons.commitFrame.amend -text "2b. Amend previous commit" -command commit_amend +pack .buttons.commitFrame.commit -fill x +pack .buttons.commitFrame.amend -fill x + +button .buttons.update -text $updateButtonText \ + -command update_lilypond_with_rebase +button .buttons.patch -text "3. Make patch set" \ + -command patch_from_origin +toggle_rebase +button .buttons.panic -text "Abort changes -- Reset to origin" \ + -command abort_changes -fg Blue -bg Red +label .buttons.spacer -text " " +if {![file exists $lily_dir]} { + .buttons.update configure \ + -text $initializeButtonText + .buttons.commitFrame.commit configure -state disabled + .buttons.commitFrame.amend configure -state disabled + .buttons.patch configure -state disabled + .buttons.panic configure -state disabled +} + +# Operating buttons + +pack .buttons.update -side left +pack .buttons.commitFrame -side left +pack .buttons.patch -side left +pack .buttons.spacer -side left +pack .buttons.panic -side right + + +# Output text box + +panedwindow .output +label .output.label -text "Command output:" +text .output.text -width 80 -height 15 \ + -xscrollcommand [list .output.horizontal set] \ + -yscrollcommand [list .output.vertical set] \ + -relief solid -border 2 +scrollbar .output.horizontal -orient h -command [list .output.text xview] +scrollbar .output.vertical -orient v -command [list .output.text yview] +pack .output.label -side left +pack .output.horizontal -side bottom -fill x +pack .output.vertical -side right -fill y +pack .output.text -expand true -anchor nw -fill both + +pack .buttons +pack .output + +#grid .buttons -row 2 -column 1 +#grid .output -row 3 -column 1 -sticky "w"