From 81347223066fee64997cbb731925bc8c1abd35d7 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 12 Feb 2007 22:48:56 -0500 Subject: [PATCH 01/16] git-gui: Refactor 'exec git subcmd' idiom. As we frequently need to execute a Git subcommand and obtain its returned output we are making heavy use of [exec git foo] to run foo. As I'm concerned about possibly needing to carry environment data through a shell on Cygwin for at least some subcommands, I'm migrating all current calls to a new git proc. This actually makes the code look cleaner too, as we aren't saying 'exec git' everywhere. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 54 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index f5010dd47a..7ecb98b900 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -46,7 +46,7 @@ proc gitdir {args} { proc gitexec {args} { global _gitexec if {$_gitexec eq {}} { - if {[catch {set _gitexec [exec git --exec-path]} err]} { + if {[catch {set _gitexec [git --exec-path]} err]} { error "Git not installed?\n\n$err" } } @@ -202,14 +202,14 @@ proc save_config {} { set value $global_config_new($name) if {$value ne $global_config($name)} { if {$value eq $default_config($name)} { - catch {exec git config --global --unset $name} + catch {git config --global --unset $name} } else { regsub -all "\[{}\]" $value {"} value - exec git config --global $name $value + git config --global $name $value } set global_config($name) $value if {$value eq $repo_config($name)} { - catch {exec git config --unset $name} + catch {git config --unset $name} set repo_config($name) $value } } @@ -219,16 +219,24 @@ proc save_config {} { set value $repo_config_new($name) if {$value ne $repo_config($name)} { if {$value eq $global_config($name)} { - catch {exec git config --unset $name} + catch {git config --unset $name} } else { regsub -all "\[{}\]" $value {"} value - exec git config $name $value + git config $name $value } set repo_config($name) $value } } } +###################################################################### +## +## handy utils + +proc git {args} { + return [eval exec git $args] +} + proc error_popup {msg} { set title [appname] if {[reponame] ne {}} { @@ -292,7 +300,7 @@ proc ask_popup {msg} { ## repository setup if { [catch {set _gitdir $env(GIT_DIR)}] - && [catch {set _gitdir [exec git rev-parse --git-dir]} err]} { + && [catch {set _gitdir [git rev-parse --git-dir]} err]} { catch {wm withdraw .} error_popup "Cannot find the git directory:\n\n$err" exit 1 @@ -365,7 +373,7 @@ proc repository_state {ctvar hdvar mhvar} { set mh [list] - if {[catch {set current_branch [exec git symbolic-ref HEAD]}]} { + if {[catch {set current_branch [git symbolic-ref HEAD]}]} { set current_branch {} } else { regsub ^refs/((heads|tags|remotes)/)? \ @@ -374,7 +382,7 @@ proc repository_state {ctvar hdvar mhvar} { current_branch } - if {[catch {set hd [exec git rev-parse --verify HEAD]}]} { + if {[catch {set hd [git rev-parse --verify HEAD]}]} { set hd {} set ct initial return @@ -402,7 +410,7 @@ proc PARENT {} { return $p } if {$empty_tree eq {}} { - set empty_tree [exec git mktree << {}] + set empty_tree [git mktree << {}] } return $empty_tree } @@ -1042,7 +1050,7 @@ proc committer_ident {} { global GIT_COMMITTER_IDENT if {$GIT_COMMITTER_IDENT eq {}} { - if {[catch {set me [exec git var GIT_COMMITTER_IDENT]} err]} { + if {[catch {set me [git var GIT_COMMITTER_IDENT]} err]} { error_popup "Unable to obtain your identity:\n\n$err" return {} } @@ -1275,7 +1283,7 @@ proc commit_committree {fd_wt curHEAD msg} { # -- Let rerere do its thing. # if {[file isdirectory [gitdir rr-cache]]} { - catch {exec git rerere} + catch {git rerere} } # -- Run the post-commit hook. @@ -1894,7 +1902,7 @@ proc do_create_branch_action {w} { focus $w.desc.name_t return } - if {![catch {exec git show-ref --verify -- "refs/heads/$newbranch"}]} { + if {![catch {git show-ref --verify -- "refs/heads/$newbranch"}]} { tk_messageBox \ -icon error \ -type ok \ @@ -1904,7 +1912,7 @@ proc do_create_branch_action {w} { focus $w.desc.name_t return } - if {[catch {exec git check-ref-format "heads/$newbranch"}]} { + if {[catch {git check-ref-format "heads/$newbranch"}]} { tk_messageBox \ -icon error \ -type ok \ @@ -1921,7 +1929,7 @@ proc do_create_branch_action {w} { tracking {set rev $create_branch_trackinghead} expression {set rev $create_branch_revexp} } - if {[catch {set cmt [exec git rev-parse --verify "${rev}^0"]}]} { + if {[catch {set cmt [git rev-parse --verify "${rev}^0"]}]} { tk_messageBox \ -icon error \ -type ok \ @@ -2100,7 +2108,7 @@ proc do_delete_branch_action {w} { } if {$check_rev eq {:none}} { set check_cmt {} - } elseif {[catch {set check_cmt [exec git rev-parse --verify "${check_rev}^0"]}]} { + } elseif {[catch {set check_cmt [git rev-parse --verify "${check_rev}^0"]}]} { tk_messageBox \ -icon error \ -type ok \ @@ -2114,10 +2122,10 @@ proc do_delete_branch_action {w} { set not_merged [list] foreach i [$w.list.l curselection] { set b [$w.list.l get $i] - if {[catch {set o [exec git rev-parse --verify $b]}]} continue + if {[catch {set o [git rev-parse --verify $b]}]} continue if {$check_cmt ne {}} { if {$b eq $check_rev} continue - if {[catch {set m [exec git merge-base $o $check_cmt]}]} continue + if {[catch {set m [git merge-base $o $check_cmt]}]} continue if {$o ne $m} { lappend not_merged $b continue @@ -2155,7 +2163,7 @@ Delete the selected branches?} foreach i $to_delete { set b [lindex $i 0] set o [lindex $i 1] - if {[catch {exec git update-ref -d "refs/heads/$b" $o} err]} { + if {[catch {git update-ref -d "refs/heads/$b" $o} err]} { append failed " - $b: $err\n" } else { set x [lsearch -sorted -exact $all_heads $b] @@ -2366,7 +2374,7 @@ Staying on branch '$current_branch'." # here, it Just Works(tm). If it doesn't we are in some really ugly # state that is difficult to recover from within git-gui. # - if {[catch {exec git symbolic-ref HEAD "refs/heads/$new_branch"} err]} { + if {[catch {git symbolic-ref HEAD "refs/heads/$new_branch"} err]} { error_popup "Failed to set current branch. This working directory is only partially switched. @@ -4161,7 +4169,7 @@ proc do_quit {} { set rc_geometry {} } if {$cfg_geometry ne $rc_geometry} { - catch {exec git config gui.geometry $cfg_geometry} + catch {git config gui.geometry $cfg_geometry} } } @@ -4412,7 +4420,7 @@ $copyright" \ set v {} append v "[appname] version $appvers\n" - append v "[exec git version]\n" + append v "[git version]\n" append v "\n" if {$tcl_patchLevel eq $tk_patchLevel} { append v "Tcl/Tk version $tcl_patchLevel" @@ -5904,7 +5912,7 @@ if {[is_enabled transport]} { if {[is_enabled multicommit]} { set object_limit 2000 if {[is_Windows]} {set object_limit 200} - regexp {^([0-9]+) objects,} [exec git count-objects] _junk objects_current + regexp {^([0-9]+) objects,} [git count-objects] _junk objects_current if {$objects_current >= $object_limit} { if {[ask_popup \ "This repository currently has $objects_current loose objects. From 54acdd95b81d3675381a749e7cd7fc14956853c3 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 13 Feb 2007 23:15:25 -0500 Subject: [PATCH 02/16] git-gui: Basic version check to ensure git 1.5.0 or later is used. This is a very crude (but hopefully effective) check against the `git` executable found in our PATH. Some of the subcommands and options that git-gui requires to be present to operate were created during the 1.5.0 development cycle, so 1.5 is the minimum version of git that we can expect to support. There actually are early releases of 1.5 (e.g. 1.5.0-rc0) that don't have everything we expect (like `blame --incremental`) but these are purely academic at this point. 1.5.0 final was tagged and released just a few hours ago. The release candidates will (hopefully) fade into the dark quickly. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index 7ecb98b900..444cc0afc8 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -295,6 +295,38 @@ proc ask_popup {msg} { -message $msg] } +###################################################################### +## +## version check + +set req_maj 1 +set req_min 5 + +if {[catch {set v [git --version]} err]} { + catch {wm withdraw .} + error_popup "Cannot determine Git version: + +$err + +[appname] requires Git $req_maj.$req_min or later." + exit 1 +} +if {[regexp {^git version (\d+)\.(\d+)} $v _junk act_maj act_min]} { + if {$act_maj < $req_maj + || ($act_maj == $req_maj && $act_min < $req_min)} { + catch {wm withdraw .} + error_popup "[appname] requires Git $req_maj.$req_min or later. + +You are using $v." + exit 1 + } +} else { + catch {wm withdraw .} + error_popup "Cannot parse Git version string:\n\n$v" + exit 1 +} +unset -nocomplain v _junk act_maj act_min req_maj req_min + ###################################################################### ## ## repository setup From cdf6e08880b4924fa717bd6ca700081f445c9065 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 13 Feb 2007 23:43:48 -0500 Subject: [PATCH 03/16] git-gui: Permit merging tags into the current branch. It was pointed out on the git mailing list by Martin Koegler that we did not show tags as possible things to merge into the current branch. They actually are, and core Git's Grand Unified Merge Driver will accept them just like any other commit. So our merge dialog now requests all refs/heads, refs/remotes and refs/tags named refs and attempts to match them against the commits not in HEAD. One complicating factor here is that we must use the %(*objectname) field when talking about an annotated tag, as they will not appear in the output of rev-list. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 444cc0afc8..f8d4db21a5 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -2916,14 +2916,16 @@ proc do_local_merge {} { pack $w.source -fill both -expand 1 -pady 5 -padx 5 set cmd [list git for-each-ref] - lappend cmd {--format=%(objectname) %(refname)} + lappend cmd {--format=%(objectname) %(*objectname) %(refname)} lappend cmd refs/heads lappend cmd refs/remotes + lappend cmd refs/tags set fr_fd [open "| $cmd" r] fconfigure $fr_fd -translation binary while {[gets $fr_fd line] > 0} { set line [split $line { }] - set sha1([lindex $line 0]) [lindex $line 1] + set sha1([lindex $line 0]) [lindex $line 2] + set sha1([lindex $line 1]) [lindex $line 2] } close $fr_fd @@ -2931,7 +2933,7 @@ proc do_local_merge {} { set fr_fd [open "| git rev-list --all --not HEAD"] while {[gets $fr_fd line] > 0} { if {[catch {set ref $sha1($line)}]} continue - regsub ^refs/(heads|remotes)/ $ref {} ref + regsub ^refs/(heads|remotes|tags)/ $ref {} ref lappend to_show $ref } close $fr_fd From 5ac58f5ba1392416a911c618abba6d874987a1b0 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Feb 2007 00:10:20 -0500 Subject: [PATCH 04/16] git-gui: More consistently display the application name. I started to find it confusing that git-gui would refer to itself as git-citool when it was started through the citool hardlink, or with the citool subcommand. What was especially confusing was the options dialog and the about dialog, as both seemed to imply they were somehow different from the git-gui versions. In actuality there is no difference at all. Now we just call our options menu item 'Options...' (skipping the application name) and our About dialog now always shows git-gui within the short description (above the copyleft notice) and in the version field. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index f8d4db21a5..b3a80c64ef 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -4442,7 +4442,7 @@ proc do_about {} { pack $w.buttons -side bottom -fill x -pady 10 -padx 10 label $w.desc \ - -text "[appname] - a commit creation tool for Git. + -text "git-gui - a commit creation tool for Git. $copyright" \ -padx 5 -pady 5 \ -justify left \ @@ -4453,7 +4453,7 @@ $copyright" \ pack $w.desc -side top -fill x -padx 5 -pady 5 set v {} - append v "[appname] version $appvers\n" + append v "git-gui version $appvers\n" append v "[git version]\n" append v "\n" if {$tcl_patchLevel eq $tk_patchLevel} { @@ -4513,7 +4513,7 @@ proc do_options {} { toplevel $w wm geometry $w "+[winfo rootx .]+[winfo rooty .]" - label $w.header -text "[appname] Options" \ + label $w.header -text "Options" \ -font font_uibold pack $w.header -side top -fill x @@ -5219,7 +5219,7 @@ if {[is_MacOSX]} { .mbar.apple add command -label "About [appname]" \ -command do_about \ -font font_ui - .mbar.apple add command -label "[appname] Options..." \ + .mbar.apple add command -label "Options..." \ -command do_options \ -font font_ui } else { From ed3adde081645c5f93685b22d39f2d74e068873d Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Feb 2007 00:28:00 -0500 Subject: [PATCH 05/16] git-gui: Print version on the console. Like `git version`, `git gui version` (or `git gui --version`) shows the version of git-gui, in case the user needs to know this, without looking at it in the GUI about dialog. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index b3a80c64ef..04afb36343 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -4987,6 +4987,8 @@ enable_option branch enable_option transport switch -- $subcommand { +--version - +version - blame { disable_option multicommit disable_option branch @@ -5322,6 +5324,11 @@ bind all <$M1B-Key-W> {destroy [winfo toplevel %W]} # -- Not a normal commit type invocation? Do that instead! # switch -- $subcommand { +--version - +version { + puts "git-gui version $appvers" + exit +} blame { if {[llength $argv] != 2} { puts stderr "usage: $argv0 blame commit path" From 26370f73c0e82bd67103e0868f84a44b536ff3fc Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Feb 2007 01:55:16 -0500 Subject: [PATCH 06/16] git-gui: Prefer version file over git-describe. Some distributions are using Git for part of their package management system, but unpack Git's own source code for delivery from the .tar.gz. This means that when we walk up the directory tree with git-describe to locate a Git repository, the repository we find is for the distribution and *not* for git-gui. Consequently any tag we might find there is bogus and does not apply to us. In this case the version file should always exist and be readable, as the packager is working from the released .tar.gz sources. So we should always favor the version file over anything git-describe guess for us. Signed-off-by: Shawn O. Pearce --- GIT-VERSION-GEN | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 9966126da2..2741c1e14c 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -20,6 +20,11 @@ tree_search () done } +# Always use the tarball version file if found, just +# in case we are somehow contained in a larger git +# repository that doesn't actually track our state. +# (At least one package manager is doing this.) +# # We may be a subproject, so try looking for the merge # commit that supplied this directory content if we are # not at the toplevel. We probably will always be the @@ -27,10 +32,13 @@ tree_search () # that fact. # # If we are at the toplevel or the merge assumption fails -# try looking for a gitgui-* tag, or fallback onto the -# distributed version file. +# try looking for a gitgui-* tag. -if prefix="$(git rev-parse --show-prefix 2>/dev/null)" +if test -f version && + VN=$(cat version) +then + : happy +elif prefix="$(git rev-parse --show-prefix 2>/dev/null)" test -n "$prefix" && head=$(git rev-list --max-count=1 HEAD -- . 2>/dev/null) && tree=$(git rev-parse --verify "HEAD:$prefix" 2>/dev/null) && @@ -48,9 +56,6 @@ elif VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && esac then VN=$(echo "$VN" | sed -e 's/^gitgui-//;s/-/./g'); -elif test -f version -then - VN=$(cat version) || VN="$DEF_VER" else VN="$DEF_VER" fi From 101e3ae7a6b041aa86505bfd3e8b901f1dc245c3 Mon Sep 17 00:00:00 2001 From: Martin Koegler Date: Thu, 15 Feb 2007 01:28:34 -0500 Subject: [PATCH 07/16] git-gui: Create new branches from a tag. I'm missing the possibility to base a new branch on a tag. The following adds a tag drop down to the new branch dialog. Signed-off-by: Martin Koegler Signed-off-by: Shawn O. Pearce --- git-gui.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index 04afb36343..9ce5a3bdc3 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1916,11 +1916,24 @@ proc all_tracking_branches {} { return [lsort -unique $all_trackings] } +proc load_all_tags {} { + set all_tags [list] + set fd [open "| git for-each-ref --format=%(refname) refs/tags" r] + while {[gets $fd line] > 0} { + if {![regsub ^refs/tags/ $line {} name]} continue + lappend all_tags $name + } + close $fd + + return [lsort $all_tags] +} + proc do_create_branch_action {w} { global all_heads null_sha1 repo_config global create_branch_checkout create_branch_revtype global create_branch_head create_branch_trackinghead global create_branch_name create_branch_revexp + global create_branch_tag set newbranch $create_branch_name if {$newbranch eq {} @@ -1959,6 +1972,7 @@ proc do_create_branch_action {w} { switch -- $create_branch_revtype { head {set rev $create_branch_head} tracking {set rev $create_branch_trackinghead} + tag {set rev $create_branch_tag} expression {set rev $create_branch_revexp} } if {[catch {set cmt [git rev-parse --verify "${rev}^0"]}]} { @@ -2004,6 +2018,8 @@ trace add variable create_branch_head write \ [list radio_selector create_branch_revtype head] trace add variable create_branch_trackinghead write \ [list radio_selector create_branch_revtype tracking] +trace add variable create_branch_tag write \ + [list radio_selector create_branch_revtype tag] trace add variable delete_branch_head write \ [list radio_selector delete_branch_checktype head] @@ -2015,6 +2031,7 @@ proc do_create_branch {} { global create_branch_checkout create_branch_revtype global create_branch_head create_branch_trackinghead global create_branch_name create_branch_revexp + global create_branch_tag set w .branch_editor toplevel $w @@ -2078,6 +2095,19 @@ proc do_create_branch {} { $all_trackings grid $w.from.tracking_r $w.from.tracking_m -sticky w } + set all_tags [load_all_tags] + if {$all_tags ne {}} { + set create_branch_tag [lindex $all_tags 0] + radiobutton $w.from.tag_r \ + -text {Tag:} \ + -value tag \ + -variable create_branch_revtype \ + -font font_ui + eval tk_optionMenu $w.from.tag_m \ + create_branch_tag \ + $all_tags + grid $w.from.tag_r $w.from.tag_m -sticky w + } radiobutton $w.from.exp_r \ -text {Revision Expression:} \ -value expression \ From b90d479255d3b47e3604493b58e271cb9cd8dccd Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 16 Feb 2007 00:24:03 -0500 Subject: [PATCH 08/16] git-gui: Expose the browser as a subcommand. Some users may find being able to browse around an arbitrary branch to be handy, so we now expose our graphical browser through `git gui browse `. Yes, I'm being somewhat lazy and making the user give us the name of the branch to browse. They can always enter HEAD. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 9ce5a3bdc3..e7898014ac 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -3044,7 +3044,14 @@ proc new_browser {commit} { global next_browser_id cursor_ptr M1B global browser_commit browser_status browser_stack browser_path browser_busy - set w .browser[incr next_browser_id] + if {[winfo ismapped .]} { + set w .browser[incr next_browser_id] + set tl $w + toplevel $w + } else { + set w {} + set tl . + } set w_list $w.list.l set browser_commit($w_list) $commit set browser_status($w_list) {Starting...} @@ -3052,7 +3059,6 @@ proc new_browser {commit} { set browser_path($w_list) $browser_commit($w_list): set browser_busy($w_list) 1 - toplevel $w label $w.path -textvariable browser_path($w_list) \ -anchor w \ -justify left \ @@ -3102,8 +3108,8 @@ proc new_browser {commit} { bind $w_list break bind $w_list break - bind $w "focus $w" - bind $w " + bind $tl "focus $w" + bind $tl " array unset browser_buffer $w_list array unset browser_files $w_list array unset browser_status $w_list @@ -3112,7 +3118,7 @@ proc new_browser {commit} { array unset browser_commit $w_list array unset browser_busy $w_list " - wm title $w "[appname] ([reponame]): File Browser" + wm title $tl "[appname] ([reponame]): File Browser" ls_tree $w_list $browser_commit($w_list) {} } @@ -5019,6 +5025,7 @@ enable_option transport switch -- $subcommand { --version - version - +browser - blame { disable_option multicommit disable_option branch @@ -5359,6 +5366,15 @@ version { puts "git-gui version $appvers" exit } +browser { + if {[llength $argv] != 1} { + puts stderr "usage: $argv0 browser commit" + exit 1 + } + set current_branch [lindex $argv 0] + new_browser $current_branch + return +} blame { if {[llength $argv] != 2} { puts stderr "usage: $argv0 blame commit path" From 372ef954a15c321a1065bf7e764449ce7767277f Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 18 Feb 2007 02:12:32 -0500 Subject: [PATCH 09/16] git-gui: Correct crash when saving options in blame mode. Martin Waitz noticed that git-gui crashed while saving the user's options out if the application was started in blame mode. This was caused by the do_save_config procedure invoking reshow_diff incase the number of context lines was modified by the user. Because we bypassed main window UI setup to enter blame mode we did not set many of the globals which were accessed by reshow_diff, and reading unset variables is an error in Tcl. Aside from moving the globals to be set earlier, I also modified reshow_diff to not invoke clear_diff if there is no path currently in the diff viewer. This way reshow_diff does not crash when in blame mode due to the $ui_diff command not being defined. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index e7898014ac..551c11c9f5 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -359,6 +359,24 @@ set _reponame [lindex [file split \ [file normalize [file dirname $_gitdir]]] \ end] +###################################################################### +## +## global init + +set current_diff_path {} +set current_diff_side {} +set diff_actions [list] +set ui_status_value {Initializing...} + +set HEAD {} +set PARENT {} +set MERGE_HEAD [list] +set commit_type {} +set empty_tree {} +set current_branch {} +set current_diff_path {} +set selected_commit_type new + ###################################################################### ## ## task management @@ -682,8 +700,9 @@ proc reshow_diff {} { global current_diff_path current_diff_side set p $current_diff_path - if {$p eq {} - || $current_diff_side eq {} + if {$p eq {}} { + # No diff is being shown. + } elseif {$current_diff_side eq {} || [catch {set s $file_states($p)}] || [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} { clear_diff @@ -5647,9 +5666,6 @@ bind_button3 $ui_comm "tk_popup $ctxm %X %Y" # -- Diff Header # -set current_diff_path {} -set current_diff_side {} -set diff_actions [list] proc trace_current_diff_path {varname args} { global current_diff_path diff_actions file_states if {$current_diff_path eq {}} { @@ -5842,7 +5858,6 @@ unset ui_diff_applyhunk # -- Status Bar # -set ui_status_value {Initializing...} label .status -textvariable ui_status_value \ -anchor w \ -justify left \ @@ -5916,15 +5931,6 @@ unset i set file_lists($ui_index) [list] set file_lists($ui_workdir) [list] -set HEAD {} -set PARENT {} -set MERGE_HEAD [list] -set commit_type {} -set empty_tree {} -set current_branch {} -set current_diff_path {} -set selected_commit_type new - wm title . "[appname] ([file normalize [file dirname [gitdir]]])" focus -force $ui_comm From ee40599330e75d9266672ed5031b3f75764fea3d Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 18 Feb 2007 19:06:09 -0500 Subject: [PATCH 10/16] git-gui: Use mixed path for docs on Cygwin. The Firefox browser requires that a URL use / to delimit directories. This is instead of \, as \ gets escaped by the browser into its hex escape code and then relative URLs are incorrectly resolved, Firefox no longer sees the directories for what they are. Since we are handing the browser a true URL, we better use the standard / for directories. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index 551c11c9f5..63848dc705 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -5336,7 +5336,7 @@ set doc_path [file dirname [gitexec]] set doc_path [file join $doc_path Documentation index.html] if {[is_Cygwin]} { - set doc_path [exec cygpath --windows $doc_path] + set doc_path [exec cygpath --mixed $doc_path] } if {$browser eq {}} { From 871f4c97ad7e021d1a0a98c80c5da77fcf70e4af Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 18 Feb 2007 21:06:48 -0500 Subject: [PATCH 11/16] git-gui: Display all authors of git-gui. Now that git-gui has been released to the public as part of Git 1.5.0 I am starting to see some work from other people beyond myself and Paul. Consequently the copyright for git-gui is not strictly the two of us anymore, and these others deserve to have some credit given to them. Signed-off-by: Shawn O. Pearce --- .gitignore | 1 + CREDITS-GEN | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 23 +++++++++++-------- git-gui.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 136 insertions(+), 10 deletions(-) create mode 100755 CREDITS-GEN diff --git a/.gitignore b/.gitignore index c714d382e8..805ca2e1c7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +CREDITS-FILE GIT-VERSION-FILE git-citool git-gui diff --git a/CREDITS-GEN b/CREDITS-GEN new file mode 100755 index 0000000000..da2c07629e --- /dev/null +++ b/CREDITS-GEN @@ -0,0 +1,58 @@ +#!/bin/sh + +CF=CREDITS-FILE +tip= + +tree_search () +{ + head=$1 + tree=$2 + for p in $(git rev-list --parents --max-count=1 $head 2>/dev/null) + do + test $tree = $(git rev-parse $p^{tree} 2>/dev/null) && + vn=$(git describe --abbrev=4 $p 2>/dev/null) && + case "$vn" in + gitgui-[0-9]*) echo $p; break;; + esac + done +} + +generate_credits () +{ + tip=$1 && + rm -f $CF && + git shortlog -n -s $tip | sed 's/: .*$//' >$CF || exit +} + +# Always use the tarball credits file if found, just +# in case we are somehow contained in a larger git +# repository that doesn't actually track our state. +# (At least one package manager is doing this.) +# +# We may be a subproject, so try looking for the merge +# commit that supplied this directory content if we are +# not at the toplevel. We probably will always be the +# second parent in the commit, but we shouldn't rely on +# that fact. +# + +if test -f credits +then + rm -f $CF && + cp credits $CF || exit +elif prefix="$(git rev-parse --show-prefix 2>/dev/null)" && + test -n "$prefix" && + head=$(git rev-list --max-count=1 HEAD -- . 2>/dev/null) && + tree=$(git rev-parse --verify "HEAD:$prefix" 2>/dev/null) && + tip=$(tree_search $head $tree) && + test -n "$tip" +then + generate_credits $tip || exit +elif tip="$(git rev-parse --verify HEAD 2>/dev/null)" && + test -n "$tip" +then + generate_credits $tip || exit +else + echo "error: Cannot locate authorship information." >&2 + exit 1 +fi diff --git a/Makefile b/Makefile index fd82d9d16d..66538ba1ad 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,8 @@ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE @$(SHELL_PATH) ./GIT-VERSION-GEN -include GIT-VERSION-FILE -SCRIPT_SH = git-gui.sh GITGUI_BUILT_INS = git-citool -ALL_PROGRAMS = $(GITGUI_BUILT_INS) $(patsubst %.sh,%,$(SCRIPT_SH)) +ALL_PROGRAMS = git-gui $(GITGUI_BUILT_INS) ifndef SHELL_PATH SHELL_PATH = /bin/sh @@ -24,20 +23,24 @@ DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) -$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh +git-gui: git-gui.sh GIT-VERSION-FILE CREDITS-FILE rm -f $@ $@+ - sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ + sed -n \ + -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ + -e '1,/^set gitgui_credits /p' \ $@.sh >$@+ + cat CREDITS-FILE >>$@+ + sed -e '1,/^set gitgui_credits /d' $@.sh >>$@+ chmod +x $@+ mv $@+ $@ +CREDITS-FILE: CREDITS-GEN .FORCE-CREDITS-FILE + $(SHELL_PATH) ./CREDITS-GEN + $(GITGUI_BUILT_INS): git-gui rm -f $@ && ln git-gui $@ -# These can record GITGUI_VERSION -$(patsubst %.sh,%,$(SCRIPT_SH)): GIT-VERSION-FILE - all:: $(ALL_PROGRAMS) install: all @@ -45,12 +48,14 @@ install: all $(INSTALL) git-gui '$(DESTDIR_SQ)$(gitexecdir_SQ)' $(foreach p,$(GITGUI_BUILT_INS), rm -f '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' && ln '$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' ;) -dist-version: +dist-version: CREDITS-FILE @mkdir -p $(TARDIR) @echo $(GITGUI_VERSION) > $(TARDIR)/version + @cat CREDITS-FILE > $(TARDIR)/credits clean:: - rm -f $(ALL_PROGRAMS) GIT-VERSION-FILE + rm -f $(ALL_PROGRAMS) GIT-VERSION-FILE CREDITS-FILE .PHONY: all install dist-version clean .PHONY: .FORCE-GIT-VERSION-FILE +.PHONY: .FORCE-CREDITS-FILE diff --git a/git-gui.sh b/git-gui.sh index 63848dc705..cd3afedc02 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -4,7 +4,7 @@ exec wish "$0" -- "$@" set appvers {@@GITGUI_VERSION@@} set copyright { -Copyright © 2006, 2007 Shawn Pearce, Paul Mackerras. +Copyright © 2006, 2007 Shawn Pearce, et. al. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA} +set gitgui_credits { +Paul Mackerras +} ###################################################################### ## @@ -4477,6 +4480,61 @@ proc do_commit {} { commit_tree } +proc do_credits {} { + global gitgui_credits + + set w .credits_dialog + + toplevel $w + wm geometry $w "+[winfo rootx .]+[winfo rooty .]" + + label $w.header -text {git-gui Contributors} -font font_uibold + pack $w.header -side top -fill x + + frame $w.buttons + button $w.buttons.close -text {Close} \ + -font font_ui \ + -command [list destroy $w] + pack $w.buttons.close -side right + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + frame $w.credits + text $w.credits.t \ + -background [$w.header cget -background] \ + -yscrollcommand [list $w.credits.sby set] \ + -width 20 \ + -height 10 \ + -wrap none \ + -borderwidth 1 \ + -relief solid \ + -padx 5 -pady 5 \ + -font font_ui + scrollbar $w.credits.sby -command [list $w.credits.t yview] + pack $w.credits.sby -side right -fill y + pack $w.credits.t -fill both -expand 1 + pack $w.credits -side top -fill both -expand 1 -padx 5 -pady 5 + + label $w.desc \ + -text "All portions are copyrighted by their respective authors +and are distributed under the GNU General Public License." \ + -padx 5 -pady 5 \ + -justify left \ + -anchor w \ + -borderwidth 1 \ + -relief solid \ + -font font_ui + pack $w.desc -side top -fill x -padx 5 -pady 5 + + $w.credits.t insert end "[string trim $gitgui_credits]\n" + $w.credits.t conf -state disabled + $w.credits.t see 1.0 + + bind $w "grab $w; focus $w" + bind $w [list destroy $w] + wm title $w [$w.header cget -text] + tkwait window $w +} + proc do_about {} { global appvers copyright global tcl_patchLevel tk_patchLevel @@ -4493,6 +4551,10 @@ proc do_about {} { button $w.buttons.close -text {Close} \ -font font_ui \ -command [list destroy $w] + button $w.buttons.credits -text {Contributors} \ + -font font_ui \ + -command do_credits + pack $w.buttons.credits -side left pack $w.buttons.close -side right pack $w.buttons -side bottom -fill x -pady 10 -padx 10 From 019f42a4ffe66e35cfe32a18c3def0183e6a0129 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 18 Feb 2007 21:08:04 -0500 Subject: [PATCH 12/16] git-gui: Change summary of git-gui. Since git-gui does more than create commits, it is unfair to call it "a commit creation tool". Instead lets just call it a graphical user interface. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index cd3afedc02..405813069b 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -4559,7 +4559,7 @@ proc do_about {} { pack $w.buttons -side bottom -fill x -pady 10 -padx 10 label $w.desc \ - -text "git-gui - a commit creation tool for Git. + -text "git-gui - a graphical user interface for Git. $copyright" \ -padx 5 -pady 5 \ -justify left \ From c0f7a6c33da7ec875fb084c9d97e471cd3a14535 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 21 Feb 2007 01:24:57 -0500 Subject: [PATCH 13/16] git-gui: Include browser in our usage message. Now that the 'browser' subcommand can be used to startup the tree browser, it should be listed as a possible subcommand option in our usage message. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-gui.sh b/git-gui.sh index 405813069b..039e7bb93f 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -5478,7 +5478,7 @@ gui { # fall through to setup UI for commits } default { - puts stderr "usage: $argv0 \[{blame|citool}\]" + puts stderr "usage: $argv0 \[{blame|browser|citool}\]" exit 1 } } From 7391b2e9991e138786a2ac049ce7f276f7abce40 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 21 Feb 2007 01:29:05 -0500 Subject: [PATCH 14/16] git-gui: Remove TODO list. I'm apparently not very good at keeping my own TODO file current. I its also somewhat strange to keep the TODO list as part of the software branch, as its meta-information that is not directly related to the code. I'm pulling the TODO list from git-gui and moving it into a seperate branch. Signed-off-by: Shawn O. Pearce --- TODO | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index b95a137322..0000000000 --- a/TODO +++ /dev/null @@ -1,44 +0,0 @@ -Items outstanding: - - * Add file to .gitignore or info/excludes. - - * Populate the pull menu with local branches. - - * Make use of the new default merge data stored in repo-config. - - * Checkout a different local branch. - - * Push any local branch to a remote branch. - - * Merge any local branches through a real merge UI. - - * Allow user to define keyboard shortcuts for frequently used fetch - or merge operations. Or maybe just define a keyboard shortcut - for default fetch/default merge of current branch is enough; - but I do know a few users who merge a couple of common branches - also into the same branch so one default isn't quite enough. - - * Better organize fetch/push/pull console windows. - - * Clone UI (to download a new repository). - - * Remotes editor (for .git/config format only). - - * Show a shortlog of the last couple of commits in the main window, - to give the user warm fuzzy feelings that we have their data - saved. Actually this may be the set of commits not yet in - the upstream (aka default merge branch remote repository). - - * GUI configuration editor for options listed in - git.git/Documentation/config.txt. Ideally this would - parse that file and generate the options dialog from - the documentation itself, and include the help text - from the documentation as part of the UI somehow. - -Known bugs: - - * git-gui sometimes just closes on Windows with no error message. - I'm not sure what the problem is here. I suspect the wish - process is just terminating due to a segfault or something, - as the do_quit proc in git-gui doesn't run. It often seems to - occur while writing a commit message in the buffer. Odd. From 981193786fc30b9ee73b9f223a75642b4ed455b9 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 21 Feb 2007 01:33:59 -0500 Subject: [PATCH 15/16] git-gui: Don't crash in citool mode on initial commit. Attempting to use `git citool` to create an initial commit caused git-gui to crash with a Tcl error as it tried to add the newly born branch to the non-existant branch menu. Moving this code to after the normal commit cleanup logic resolves the issue, as we only have a branch menu if we are not in singlecommit mode. Signed-off-by: Shawn O. Pearce --- git-gui.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/git-gui.sh b/git-gui.sh index 039e7bb93f..f84ba3382b 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -1318,14 +1318,6 @@ proc commit_committree {fd_wt curHEAD msg} { return } - # -- Make sure our current branch exists. - # - if {$commit_type eq {initial}} { - lappend all_heads $current_branch - set all_heads [lsort -unique $all_heads] - populate_branch_menu - } - # -- Cleanup after ourselves. # catch {file delete $msg_p} @@ -1361,6 +1353,14 @@ proc commit_committree {fd_wt curHEAD msg} { if {[is_enabled singlecommit]} do_quit + # -- Make sure our current branch exists. + # + if {$commit_type eq {initial}} { + lappend all_heads $current_branch + set all_heads [lsort -unique $all_heads] + populate_branch_menu + } + # -- Update in memory status # set selected_commit_type new From c750da256a54f189de28d3deb054328d67f9b9be Mon Sep 17 00:00:00 2001 From: Michael Loeffler Date: Wed, 14 Feb 2007 17:03:12 +0100 Subject: [PATCH 16/16] Use gunzip -c over gzcat in import-tars example. Not everyone has gzcat or bzcat installed on their system, but gunzip -c and bunzip2 -c perform the same task and are available if the user has installed gzip support or bzip2 support. Signed-off-by: Michael Loeffler Signed-off-by: Shawn O. Pearce --- contrib/fast-import/import-tars.perl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl index 990c9e70b2..5585a8b2c5 100755 --- a/contrib/fast-import/import-tars.perl +++ b/contrib/fast-import/import-tars.perl @@ -25,11 +25,14 @@ foreach my $tar_file (@ARGV) my $tar_name = $1; if ($tar_name =~ s/\.(tar\.gz|tgz)$//) { - open(I, '-|', 'gzcat', $tar_file) or die "Unable to gzcat $tar_file: $!\n"; + open(I, '-|', 'gunzip', '-c', $tar_file) + or die "Unable to gunzip -c $tar_file: $!\n"; } elsif ($tar_name =~ s/\.(tar\.bz2|tbz2)$//) { - open(I, '-|', 'bzcat', $tar_file) or die "Unable to bzcat $tar_file: $!\n"; + open(I, '-|', 'bunzip2', '-c', $tar_file) + or die "Unable to bunzip2 -c $tar_file: $!\n"; } elsif ($tar_name =~ s/\.tar\.Z$//) { - open(I, '-|', 'zcat', $tar_file) or die "Unable to zcat $tar_file: $!\n"; + open(I, '-|', 'uncompress', '-c', $tar_file) + or die "Unable to uncompress -c $tar_file: $!\n"; } elsif ($tar_name =~ s/\.tar$//) { open(I, $tar_file) or die "Unable to open $tar_file: $!\n"; } else {