Commits

Junio C Hamano  committed 9269df9 Merge

Merge branch 'maint' of git://repo.or.cz/git-gui into maint

* 'maint' of git://repo.or.cz/git-gui:
git-gui: Disable native platform text selection in "lists"
git-gui: Paper bag fix "Commit->Revert" format arguments
git-gui: Provide 'uninstall' Makefile target to undo an installation
git-gui: Font chooser to handle a large number of font families
git-gui: Make backporting changes from i18n version easier
git-gui: Don't delete send on Windows as it doesn't exist
git-gui: Trim trailing slashes from untracked submodule names
git-gui: Assume untracked directories are Git submodules
git-gui: handle "deleted symlink" diff marker
git-gui: show unstaged symlinks in diff viewer
git-gui: Avoid use of libdir in Makefile
git-gui: Disable Tk send in all git-gui sessions
git-gui: lib/index.tcl: handle files with % in the filename properly
git-gui: Properly set the state of "Stage/Unstage Hunk" action
git-gui: Fix detaching current branch during checkout
git-gui: Correct starting of git-remote to handle -w option

  • Participants
  • Parent commits be510cf, 3849bfb

Comments (0)

Files changed (8)

File git-gui/Makefile

 	INSTALL = install
 endif
 
+RM_F      ?= rm -f
+RMDIR     ?= rmdir
+
 INSTALL_D0 = $(INSTALL) -d -m755 # space is required here
 INSTALL_D1 =
 INSTALL_R0 = $(INSTALL) -m644 # space is required here
 INSTALL_L2 =
 INSTALL_L3 =
 
+REMOVE_D0  = $(RMDIR) # space is required here
+REMOVE_D1  = || true
+REMOVE_F0  = $(RM_F) # space is required here
+REMOVE_F1  =
+CLEAN_DST  = true
+
 ifndef V
 	QUIET          = @
 	QUIET_GEN      = $(QUIET)echo '   ' GEN $@ &&
 	INSTALL_L1 = && src=
 	INSTALL_L2 = && dst=
 	INSTALL_L3 = && echo '   ' 'LINK       ' `basename "$$dst"` '->' `basename "$$src"` && rm -f "$$dst" && ln "$$src" "$$dst"
+
+	CLEAN_DST = echo ' ' UNINSTALL
+	REMOVE_D0 = dir=
+	REMOVE_D1 = && echo ' ' REMOVE $$dir && test -d "$$dir" && $(RMDIR) "$$dir" || true
+	REMOVE_F0 = dst=
+	REMOVE_F1 = && echo '   ' REMOVE `basename "$$dst"` && $(RM_F) "$$dst"
 endif
 
 TCL_PATH   ?= tclsh
 TCL_PATH_SQ = $(subst ','\'',$(TCL_PATH))
 TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 
-libdir   ?= $(sharedir)/git-gui/lib
-libdir_SQ = $(subst ','\'',$(libdir))
+gg_libdir ?= $(sharedir)/git-gui/lib
+libdir_SQ  = $(subst ','\'',$(gg_libdir))
 
 exedir    = $(dir $(gitexecdir))share/git-gui/lib
 exedir_SQ = $(subst ','\'',$(exedir))
 	$(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \
 	$(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \
 	$(subst ','\'',gitexecdir='$(gitexecdir_SQ)') \
-	$(subst ','\'',libdir='$(libdir_SQ)') \
+	$(subst ','\'',gg_libdir='$(libdir_SQ)') \
 #end TRACK_VARS
 
 GIT-GUI-VARS: .FORCE-GIT-GUI-VARS
 	$(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)'
 	$(QUIET)$(foreach p,$(ALL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true
 
+uninstall:
+	$(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
+	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1)
+	$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true
+	$(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)'
+	$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1)
+	$(QUIET)$(foreach p,$(ALL_LIBFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true
+	$(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(REMOVE_D1)
+	$(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(REMOVE_D1)
+	$(QUIET)$(REMOVE_D0)`dirname '$(DESTDIR_SQ)$(libdir_SQ)'` $(REMOVE_D1)
+
 dist-version:
 	@mkdir -p $(TARDIR)
 	@echo $(GITGUI_VERSION) > $(TARDIR)/version
 	rm -f $(ALL_PROGRAMS) lib/tclIndex
 	rm -f GIT-VERSION-FILE GIT-GUI-VARS
 
-.PHONY: all install dist-version clean
+.PHONY: all install uninstall dist-version clean
 .PHONY: .FORCE-GIT-VERSION-FILE
 .PHONY: .FORCE-GIT-GUI-VARS

File git-gui/git-gui.sh

 	exit 1
 }
 
+catch {rename send {}} ; # What an evil concept...
+
 ######################################################################
 ##
 ## enable verbose loading?
 
 ######################################################################
 ##
+## Fake internationalization to ease backporting of changes.
+
+proc mc {fmt args} {
+	set cmk [string first @@ $fmt]
+	if {$cmk > 0} {
+		set fmt [string range $fmt 0 [expr {$cmk - 1}]]
+	}
+	return [eval [list format $fmt] $args]
+}
+
+######################################################################
+##
 ## read only globals
 
 set _appname [lindex [file split $argv0] end]
 			set s [gets $f]
 			close $f
 
-			switch -glob -- $s {
+			switch -glob -- [lindex $s 0] {
 			#!*sh     { set i sh     }
 			#!*perl   { set i perl   }
 			#!*python { set i python }
 			if {$interp eq {}} {
 				error "git-$name requires $i (not in PATH)"
 			}
-			set v [list $interp $p]
+			set v [concat [list $interp] [lrange $s 1 end] [list $p]]
 		} else {
 			# Assume it is builtin to git somehow and we
 			# aren't actually able to see a file for it.
 	return $m
 }
 
+proc rmsel_tag {text} {
+	$text tag conf sel \
+		-background [$text cget -background] \
+		-foreground [$text cget -foreground] \
+		-borderwidth 0
+	$text tag conf in_sel -background lightgray
+	bind $text <Motion> break
+	return $text
+}
+
 ######################################################################
 ##
 ## find git
 	set pck [split $buf_rlo "\0"]
 	set buf_rlo [lindex $pck end]
 	foreach p [lrange $pck 0 end-1] {
-		merge_state [encoding convertfrom $p] ?O
+		set p [encoding convertfrom $p]
+		if {[string index $p end] eq {/}} {
+			set p [string range $p 0 end-1]
+		}
+		merge_state $p ?O
 	}
 	rescan_done $fd buf_rlo $after
 }
 .vpane.files add .vpane.files.workdir -sticky nsew
 
 foreach i [list $ui_index $ui_workdir] {
-	$i tag conf in_diff -background lightgray
-	$i tag conf in_sel  -background lightgray
+	rmsel_tag $i
+	$i tag conf in_diff -background [$i tag cget in_sel -background]
 }
 unset i
 
 	set ::cursorX $x
 	set ::cursorY $y
 	if {$::ui_index eq $::current_diff_side} {
-		set s normal
 		set l "Unstage Hunk From Commit"
 	} else {
-		if {$current_diff_path eq {}
-			|| ![info exists file_states($current_diff_path)]
-			|| {_O} eq [lindex $file_states($current_diff_path) 0]} {
-			set s disabled
-		} else {
-			set s normal
-		}
 		set l "Stage Hunk For Commit"
 	}
-	if {$::is_3way_diff} {
+	if {$::is_3way_diff
+		|| $current_diff_path eq {}
+		|| ![info exists file_states($current_diff_path)]
+		|| {_O} eq [lindex $file_states($current_diff_path) 0]} {
 		set s disabled
+	} else {
+		set s normal
 	}
 	$ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
 	tk_popup $ctxm $X $Y

File git-gui/lib/browser.tcl

 		-width 70 \
 		-xscrollcommand [list $w.list.sbx set] \
 		-yscrollcommand [list $w.list.sby set]
-	$w_list tag conf in_sel \
-		-background [$w_list cget -foreground] \
-		-foreground [$w_list cget -background]
+	rmsel_tag $w_list
 	scrollbar $w.list.sbx -orient h -command [list $w_list xview]
 	scrollbar $w.list.sby -orient v -command [list $w_list yview]
 	pack $w.list.sbx -side bottom -fill x

File git-gui/lib/checkout_op.tcl

 			set is_detached 0
 		}
 	} else {
-		if {$new_hash ne $HEAD} {
+		if {!$is_detached || $new_hash ne $HEAD} {
 			append log " to $new_expr"
 			if {[catch {
 					_detach_HEAD $log $new_hash

File git-gui/lib/choose_font.tcl

+# git-gui font chooser
+# Copyright (C) 2007 Shawn Pearce
+
+class choose_font {
+
+field w
+field w_family    ; # UI widget of all known family names
+field w_example   ; # Example to showcase the chosen font
+
+field f_family    ; # Currently chosen family name
+field f_size      ; # Currently chosen point size
+
+field v_family    ; # Name of global variable for family
+field v_size      ; # Name of global variable for size
+
+variable all_families [list]  ; # All fonts known to Tk
+
+constructor pick {path title a_family a_size} {
+	variable all_families
+
+	set v_family $a_family
+	set v_size $a_size
+
+	upvar #0 $v_family pv_family
+	upvar #0 $v_size pv_size
+
+	set f_family $pv_family
+	set f_size $pv_size
+
+	make_toplevel top w
+	wm title $top "[appname] ([reponame]): $title"
+	wm geometry $top "+[winfo rootx $path]+[winfo rooty $path]"
+
+	label $w.header -text $title -font font_uibold
+	pack $w.header -side top -fill x
+
+	frame $w.buttons
+	button $w.buttons.select \
+		-text [mc Select] \
+		-default active \
+		-command [cb _select]
+	button $w.buttons.cancel \
+		-text [mc Cancel] \
+		-command [list destroy $w]
+	pack $w.buttons.select -side right
+	pack $w.buttons.cancel -side right -padx 5
+	pack $w.buttons -side bottom -fill x -pady 10 -padx 10
+
+	frame $w.inner
+
+	frame $w.inner.family
+	label $w.inner.family.l \
+		-text [mc "Font Family"] \
+		-anchor w
+	set w_family $w.inner.family.v
+	text $w_family \
+		-background white \
+		-borderwidth 1 \
+		-relief sunken \
+		-cursor $::cursor_ptr \
+		-wrap none \
+		-width 30 \
+		-height 10 \
+		-yscrollcommand [list $w.inner.family.sby set]
+	rmsel_tag $w_family
+	scrollbar $w.inner.family.sby -command [list $w_family yview]
+	pack $w.inner.family.l -side top -fill x
+	pack $w.inner.family.sby -side right -fill y
+	pack $w_family -fill both -expand 1
+
+	frame $w.inner.size
+	label $w.inner.size.l \
+		-text [mc "Font Size"] \
+		-anchor w
+	spinbox $w.inner.size.v \
+		-textvariable @f_size \
+		-from 2 -to 80 -increment 1 \
+		-width 3
+	bind $w.inner.size.v <FocusIn> {%W selection range 0 end}
+	pack $w.inner.size.l -fill x -side top
+	pack $w.inner.size.v -fill x -padx 2
+
+	grid configure $w.inner.family $w.inner.size -sticky nsew
+	grid rowconfigure $w.inner 0 -weight 1
+	grid columnconfigure $w.inner 0 -weight 1
+	pack $w.inner -fill both -expand 1 -padx 5 -pady 5
+
+	frame $w.example
+	label $w.example.l \
+		-text [mc "Font Example"] \
+		-anchor w
+	set w_example $w.example.t
+	text $w_example \
+		-background white \
+		-borderwidth 1 \
+		-relief sunken \
+		-height 3 \
+		-width 40
+	rmsel_tag $w_example
+	$w_example tag conf example -justify center
+	$w_example insert end [mc "This is example text.\nIf you like this text, it can be your font."] example
+	$w_example conf -state disabled
+	pack $w.example.l -fill x
+	pack $w_example -fill x
+	pack $w.example -fill x -padx 5
+
+	if {$all_families eq {}} {
+		set all_families [lsort [font families]]
+	}
+
+	$w_family tag conf pick
+	$w_family tag bind pick <Button-1> [cb _pick_family %x %y]\;break
+	foreach f $all_families {
+		set sel [list pick]
+		if {$f eq $f_family} {
+			lappend sel in_sel
+		}
+		$w_family insert end "$f\n" $sel
+	}
+	$w_family conf -state disabled
+	_update $this
+
+	trace add variable @f_size write [cb _update]
+	bind $w <Key-Escape> [list destroy $w]
+	bind $w <Key-Return> [cb _select]\;break
+	bind $w <Visibility> "
+		grab $w
+		focus $w
+	"
+	tkwait window $w
+}
+
+method _select {} {
+	upvar #0 $v_family pv_family
+	upvar #0 $v_size pv_size
+
+	set pv_family $f_family
+	set pv_size $f_size
+
+	destroy $w
+}
+
+method _pick_family {x y} {
+	variable all_families
+
+	set i [lindex [split [$w_family index @$x,$y] .] 0]
+	set n [lindex $all_families [expr {$i - 1}]]
+	if {$n ne {}} {
+		$w_family tag remove in_sel 0.0 end
+		$w_family tag add in_sel $i.0 [expr {$i + 1}].0
+		set f_family $n
+		_update $this
+	}
+}
+
+method _update {args} {
+	variable all_families
+
+	set i [lsearch -exact $all_families $f_family]
+	if {$i < 0} return
+
+	$w_example tag conf example -font [list $f_family $f_size]
+	$w_family see [expr {$i + 1}].0
+}
+
+}

File git-gui/lib/diff.tcl

 	#
 	if {$m eq {_O}} {
 		set max_sz [expr {128 * 1024}]
+		set type unknown
 		if {[catch {
-				set fd [open $path r]
-				fconfigure $fd -eofchar {}
-				set content [read $fd $max_sz]
-				close $fd
-				set sz [file size $path]
+				set type [file type $path]
+				switch -- $type {
+				directory {
+					set type submodule
+					set content {}
+					set sz 0
+				}
+				link {
+					set content [file readlink $path]
+					set sz [string length $content]
+				}
+				file {
+					set fd [open $path r]
+					fconfigure $fd -eofchar {}
+					set content [read $fd $max_sz]
+					close $fd
+					set sz [file size $path]
+				}
+				default {
+					error "'$type' not supported"
+				}
+				}
 			} err ]} {
 			set diff_active 0
 			unlock_index
 			return
 		}
 		$ui_diff conf -state normal
-		if {![catch {set type [exec file $path]}]} {
+		if {$type eq {submodule}} {
+			$ui_diff insert end "* Git Repository (subproject)\n" d_@
+		} elseif {![catch {set type [exec file $path]}]} {
 			set n [string length $path]
 			if {[string equal -length $n $path $type]} {
 				set type [string range $type $n end]
 		if {[string match {mode *} $line]
 			|| [string match {new file *} $line]
 			|| [string match {deleted file *} $line]
+			|| [string match {deleted symlink} $line]
 			|| [string match {Binary files * and * differ} $line]
 			|| $line eq {\ No newline at end of file}
 			|| [regexp {^\* Unmerged path } $line]} {

File git-gui/lib/index.tcl

 	if {$batch > 25} {set batch 25}
 
 	ui_status [format \
-		"$msg... %i/%i files (%.2f%%)" \
+		"%s... %i/%i files (%.2f%%)" \
+		$msg \
 		$update_index_cp \
 		$totalCnt \
 		0.0]
 	}
 
 	ui_status [format \
-		"$msg... %i/%i files (%.2f%%)" \
+		"%s... %i/%i files (%.2f%%)" \
+		$msg \
 		$update_index_cp \
 		$totalCnt \
 		[expr {100.0 * $update_index_cp / $totalCnt}]]
 	if {$batch > 25} {set batch 25}
 
 	ui_status [format \
-		"$msg... %i/%i files (%.2f%%)" \
+		"%s... %i/%i files (%.2f%%)" \
+		$msg \
 		$update_index_cp \
 		$totalCnt \
 		0.0]
 	}
 
 	ui_status [format \
-		"$msg... %i/%i files (%.2f%%)" \
+		"%s... %i/%i files (%.2f%%)" \
+		$msg \
 		$update_index_cp \
 		$totalCnt \
 		[expr {100.0 * $update_index_cp / $totalCnt}]]
 	if {$batch > 25} {set batch 25}
 
 	ui_status [format \
-		"$msg... %i/%i files (%.2f%%)" \
+		"%s... %i/%i files (%.2f%%)" \
+		$msg \
 		$update_index_cp \
 		$totalCnt \
 		0.0]
 	}
 
 	ui_status [format \
-		"$msg... %i/%i files (%.2f%%)" \
+		"%s... %i/%i files (%.2f%%)" \
+		$msg \
 		$update_index_cp \
 		$totalCnt \
 		[expr {100.0 * $update_index_cp / $totalCnt}]]

File git-gui/lib/option.tcl

 
 		frame $w.global.$name
 		label $w.global.$name.l -text "$text:"
-		pack $w.global.$name.l -side left -anchor w -fill x
-		eval tk_optionMenu $w.global.$name.family \
-			global_config_new(gui.$font^^family) \
-			$all_fonts
-		spinbox $w.global.$name.size \
-			-textvariable global_config_new(gui.$font^^size) \
-			-from 2 -to 80 -increment 1 \
-			-width 3
-		bind $w.global.$name.size <FocusIn> {%W selection range 0 end}
-		pack $w.global.$name.size -side right -anchor e
-		pack $w.global.$name.family -side right -anchor e
+		button $w.global.$name.b \
+			-text [mc "Change Font"] \
+			-command [list \
+				choose_font::pick \
+				$w \
+				[mc "Choose %s" $text] \
+				global_config_new(gui.$font^^family) \
+				global_config_new(gui.$font^^size) \
+				]
+		label $w.global.$name.f -textvariable global_config_new(gui.$font^^family)
+		label $w.global.$name.s -textvariable global_config_new(gui.$font^^size)
+		label $w.global.$name.pt -text [mc "pt."]
+		pack $w.global.$name.l -side left -anchor w
+		pack $w.global.$name.b -side right -anchor e
+		pack $w.global.$name.pt -side right -anchor w
+		pack $w.global.$name.s -side right -anchor w
+		pack $w.global.$name.f -side right -anchor w
 		pack $w.global.$name -side top -anchor w -fill x
 	}