From: Junio C Hamano Date: Wed, 13 Feb 2008 19:04:58 +0000 (-0800) Subject: Merge git://repo.or.cz/git-gui X-Git-Tag: v1.5.5-rc0~222 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=41e2edf41a6d501f1b8beca7f1f0bcbe9296dcc2;p=git.git Merge git://repo.or.cz/git-gui * git://repo.or.cz/git-gui: git-gui: Automatically spell check commit messages as the user types git-gui: support Git Gui.app under OS X 10.5 git-gui: Update German translation. git-gui: (i18n) Fix a bunch of still untranslated strings. --- 41e2edf41a6d501f1b8beca7f1f0bcbe9296dcc2 diff --cc git-gui/Makefile index 34438cdf5,000000000..081d7550a mode 100644,000000..100644 --- a/git-gui/Makefile +++ b/git-gui/Makefile @@@ -1,311 -1,0 +1,320 @@@ +all:: + +# Define V=1 to have a more verbose compile. +# +# Define NO_MSGFMT if you do not have msgfmt from the GNU gettext +# package and want to use our rough pure Tcl po->msg translator. +# TCL_PATH must be vaild for this to work. +# + +GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE + @$(SHELL_PATH) ./GIT-VERSION-GEN +-include GIT-VERSION-FILE + +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') +uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') ++uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') + +SCRIPT_SH = git-gui.sh +GITGUI_MAIN := git-gui +GITGUI_BUILT_INS = git-citool +ALL_LIBFILES = $(wildcard lib/*.tcl) +PRELOAD_FILES = lib/class.tcl +NONTCL_LIBFILES = \ + lib/git-gui.ico \ + $(wildcard lib/win32_*.js) \ +#end NONTCL_LIBFILES + +ifndef SHELL_PATH + SHELL_PATH = /bin/sh +endif + +ifndef gitexecdir + gitexecdir := $(shell git --exec-path) +endif + +ifndef sharedir + sharedir := $(dir $(gitexecdir))share +endif + +ifndef INSTALL + INSTALL = install +endif + +RM_RF ?= rm -rf +RMDIR ?= rmdir + +INSTALL_D0 = $(INSTALL) -d -m 755 # space is required here +INSTALL_D1 = +INSTALL_R0 = $(INSTALL) -m 644 # space is required here +INSTALL_R1 = +INSTALL_X0 = $(INSTALL) -m 755 # space is required here +INSTALL_X1 = +INSTALL_A0 = find # space is required here +INSTALL_A1 = | cpio -pud +INSTALL_L0 = rm -f # space is required here +INSTALL_L1 = && ln # space is required here +INSTALL_L2 = +INSTALL_L3 = + +REMOVE_D0 = $(RMDIR) # space is required here +REMOVE_D1 = || true +REMOVE_F0 = $(RM_RF) # space is required here +REMOVE_F1 = +CLEAN_DST = true + +ifndef V + QUIET = @ + QUIET_GEN = $(QUIET)echo ' ' GEN '$@' && + QUIET_INDEX = $(QUIET)echo ' ' INDEX $(dir $@) && + QUIET_MSGFMT0 = $(QUIET)printf ' MSGFMT %12s ' $@ && v=` + QUIET_MSGFMT1 = 2>&1` && echo "$$v" | sed -e 's/fuzzy translations/fuzzy/' | sed -e 's/ messages*//g' + QUIET_2DEVNULL = 2>/dev/null + + INSTALL_D0 = dir= + INSTALL_D1 = && echo ' ' DEST $$dir && $(INSTALL) -d -m 755 "$$dir" + INSTALL_R0 = src= + INSTALL_R1 = && echo ' ' INSTALL 644 `basename $$src` && $(INSTALL) -m 644 $$src + INSTALL_X0 = src= + INSTALL_X1 = && echo ' ' INSTALL 755 `basename $$src` && $(INSTALL) -m 755 $$src + INSTALL_A0 = src= + INSTALL_A1 = && echo ' ' INSTALL ' ' `basename "$$src"` && find "$$src" | cpio -pud + + INSTALL_L0 = dst= + 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_RF) "$$dst" +endif + +TCL_PATH ?= tclsh +TCLTK_PATH ?= wish - TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app ++ ++ifeq ($(uname_S),Darwin) ++ TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app ++ ifeq ($(shell expr "$(uname_R)" : '9\.'),2) ++ TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app ++ endif ++ TKEXECUTABLE = $(shell basename "$(TKFRAMEWORK)" .app) ++endif + +ifeq ($(findstring $(MAKEFLAGS),s),s) +QUIET_GEN = +endif + +-include config.mak + +DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) +gitexecdir_SQ = $(subst ','\'',$(gitexecdir)) +SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) +TCL_PATH_SQ = $(subst ','\'',$(TCL_PATH)) +TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH)) +TCLTK_PATH_SED = $(subst ','\'',$(subst \,\\,$(TCLTK_PATH))) + +gg_libdir ?= $(sharedir)/git-gui/lib +libdir_SQ = $(subst ','\'',$(gg_libdir)) +libdir_SED = $(subst ','\'',$(subst \,\\,$(gg_libdir_sed_in))) +exedir = $(dir $(gitexecdir))share/git-gui/lib + +GITGUI_SCRIPT := $$0 +GITGUI_RELATIVE := +GITGUI_MACOSXAPP := + +ifeq ($(uname_O),Cygwin) + GITGUI_SCRIPT := `cygpath --windows --absolute "$(GITGUI_SCRIPT)"` + gg_libdir_sed_in := $(shell cygpath --windows --absolute "$(gg_libdir)") +else + ifeq ($(exedir),$(gg_libdir)) + GITGUI_RELATIVE := 1 + endif + gg_libdir_sed_in := $(gg_libdir) +endif +ifeq ($(uname_S),Darwin) + ifeq ($(shell test -d $(TKFRAMEWORK) && echo y),y) + GITGUI_MACOSXAPP := YesPlease + endif +endif +ifneq (,$(findstring MINGW,$(uname_S))) + NO_MSGFMT=1 + GITGUI_WINDOWS_WRAPPER := YesPlease +endif + +ifdef GITGUI_MACOSXAPP +GITGUI_MAIN := git-gui.tcl + +git-gui: GIT-VERSION-FILE GIT-GUI-VARS + $(QUIET_GEN)rm -f $@ $@+ && \ + echo '#!$(SHELL_PATH_SQ)' >$@+ && \ + echo 'if test "z$$*" = zversion ||' >>$@+ && \ + echo ' test "z$$*" = z--version' >>$@+ && \ + echo then >>$@+ && \ + echo ' 'echo \'git-gui version '$(GITGUI_VERSION)'\' >>$@+ && \ + echo else >>$@+ && \ - echo ' 'exec \''$(libdir_SQ)/Git Gui.app/Contents/MacOS/Wish'\' \ ++ echo ' 'exec \''$(libdir_SQ)/Git Gui.app/Contents/MacOS/$(subst \,,$(TKEXECUTABLE))'\' \ + '"$$0" "$$@"' >>$@+ && \ + echo fi >>$@+ && \ + chmod +x $@+ && \ + mv $@+ $@ + +Git\ Gui.app: GIT-VERSION-FILE GIT-GUI-VARS \ + macosx/Info.plist \ + macosx/git-gui.icns \ + macosx/AppMain.tcl \ - $(TKFRAMEWORK)/Contents/MacOS/Wish ++ $(TKFRAMEWORK)/Contents/MacOS/$(TKEXECUTABLE) + $(QUIET_GEN)rm -rf '$@' '$@'+ && \ + mkdir -p '$@'+/Contents/MacOS && \ + mkdir -p '$@'+/Contents/Resources/Scripts && \ - cp '$(subst ','\'',$(TKFRAMEWORK))/Contents/MacOS/Wish' \ ++ cp '$(subst ','\'',$(subst \,,$(TKFRAMEWORK)/Contents/MacOS/$(TKEXECUTABLE)))' \ + '$@'+/Contents/MacOS && \ + cp macosx/git-gui.icns '$@'+/Contents/Resources && \ + sed -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ ++ -e 's/@@GITGUI_TKEXECUTABLE@@/$(TKEXECUTABLE)/g' \ + macosx/Info.plist \ + >'$@'+/Contents/Info.plist && \ + sed -e 's|@@gitexecdir@@|$(gitexecdir_SQ)|' \ + -e 's|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \ + macosx/AppMain.tcl \ + >'$@'+/Contents/Resources/Scripts/AppMain.tcl && \ + mv '$@'+ '$@' +endif + +ifdef GITGUI_WINDOWS_WRAPPER +GITGUI_MAIN := git-gui.tcl + +git-gui: windows/git-gui.sh + cp $< $@ +endif + +$(GITGUI_MAIN): git-gui.sh GIT-VERSION-FILE GIT-GUI-VARS + $(QUIET_GEN)rm -f $@ $@+ && \ + sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ + -e '1,30s|^ argv0=$$0| argv0=$(GITGUI_SCRIPT)|' \ + -e '1,30s|^ exec wish | exec '\''$(TCLTK_PATH_SED)'\'' |' \ + -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \ + -e 's|@@GITGUI_RELATIVE@@|$(GITGUI_RELATIVE)|' \ + -e '$(GITGUI_RELATIVE)s|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \ + git-gui.sh >$@+ && \ + chmod +x $@+ && \ + mv $@+ $@ + +XGETTEXT ?= xgettext +ifdef NO_MSGFMT + MSGFMT ?= $(TCL_PATH) po/po2msg.sh +else + MSGFMT ?= msgfmt + ifeq ($(shell $(MSGFMT) >/dev/null 2>&1 || echo $$?),127) + MSGFMT := $(TCL_PATH) po/po2msg.sh + endif +endif + +msgsdir = $(gg_libdir)/msgs +msgsdir_SQ = $(subst ','\'',$(msgsdir)) +PO_TEMPLATE = po/git-gui.pot +ALL_POFILES = $(wildcard po/*.po) +ALL_MSGFILES = $(subst .po,.msg,$(ALL_POFILES)) + +$(PO_TEMPLATE): $(SCRIPT_SH) $(ALL_LIBFILES) + $(XGETTEXT) -kmc -LTcl -o $@ $(SCRIPT_SH) $(ALL_LIBFILES) +update-po:: $(PO_TEMPLATE) + $(foreach p, $(ALL_POFILES), echo Updating $p ; msgmerge -U $p $(PO_TEMPLATE) ; ) +$(ALL_MSGFILES): %.msg : %.po + $(QUIET_MSGFMT0)$(MSGFMT) --statistics --tcl -l $(basename $(notdir $<)) -d $(dir $@) $< $(QUIET_MSGFMT1) + +lib/tclIndex: $(ALL_LIBFILES) GIT-GUI-VARS + $(QUIET_INDEX)if echo \ + $(foreach p,$(PRELOAD_FILES),source $p\;) \ + auto_mkindex lib '*.tcl' \ + | $(TCL_PATH) $(QUIET_2DEVNULL); then : ok; \ + else \ + echo 1>&2 " * $(TCL_PATH) failed; using unoptimized loading"; \ + rm -f $@ ; \ + echo '# Autogenerated by git-gui Makefile' >$@ && \ + echo >>$@ && \ + $(foreach p,$(PRELOAD_FILES) $(ALL_LIBFILES),echo '$(subst lib/,,$p)' >>$@ &&) \ + echo >>$@ ; \ + fi + +TRACK_VARS = \ + $(subst ','\'',SHELL_PATH='$(SHELL_PATH_SQ)') \ + $(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \ + $(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \ + $(subst ','\'',gitexecdir='$(gitexecdir_SQ)') \ + $(subst ','\'',gg_libdir='$(libdir_SQ)') \ + GITGUI_MACOSXAPP=$(GITGUI_MACOSXAPP) \ +#end TRACK_VARS + +GIT-GUI-VARS: .FORCE-GIT-GUI-VARS + @VARS='$(TRACK_VARS)'; \ + if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \ + echo 1>&2 " * new locations or Tcl/Tk interpreter"; \ + echo 1>$@ "$$VARS"; \ + fi + +ifdef GITGUI_MACOSXAPP +all:: git-gui Git\ Gui.app +endif +ifdef GITGUI_WINDOWS_WRAPPER +all:: git-gui +endif +all:: $(GITGUI_MAIN) lib/tclIndex $(ALL_MSGFILES) + +install: all + $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1) + $(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)' + $(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true +ifdef GITGUI_WINDOWS_WRAPPER + $(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)' +endif + $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1) + $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' +ifdef GITGUI_MACOSXAPP + $(QUIET)$(INSTALL_A0)'Git Gui.app' $(INSTALL_A1) '$(DESTDIR_SQ)$(libdir_SQ)' + $(QUIET)$(INSTALL_X0)git-gui.tcl $(INSTALL_X1) '$(DESTDIR_SQ)$(libdir_SQ)' +endif + $(QUIET)$(foreach p,$(ALL_LIBFILES) $(NONTCL_LIBFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)' &&) true + $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(msgsdir_SQ)' $(INSTALL_D1) + $(QUIET)$(foreach p,$(ALL_MSGFILES), $(INSTALL_R0)$p $(INSTALL_R1) '$(DESTDIR_SQ)$(msgsdir_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 +ifdef GITGUI_WINDOWS_WRAPPER + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1) +endif + $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)' + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1) +ifdef GITGUI_MACOSXAPP + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)/Git Gui.app' $(REMOVE_F1) + $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.tcl $(REMOVE_F1) +endif + $(QUIET)$(foreach p,$(ALL_LIBFILES) $(NONTCL_LIBFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true + $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(msgsdir_SQ)' + $(QUIET)$(foreach p,$(ALL_MSGFILES), $(REMOVE_F0)'$(DESTDIR_SQ)$(msgsdir_SQ)'/$(notdir $p) $(REMOVE_F1) &&) true + $(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(REMOVE_D1) + $(QUIET)$(REMOVE_D0)'$(DESTDIR_SQ)$(msgsdir_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 + +clean:: + $(RM_RF) $(GITGUI_MAIN) lib/tclIndex po/*.msg + $(RM_RF) GIT-VERSION-FILE GIT-GUI-VARS +ifdef GITGUI_MACOSXAPP + $(RM_RF) 'Git Gui.app'* git-gui +endif +ifdef GITGUI_WINDOWS_WRAPPER + $(RM_RF) git-gui +endif + +.PHONY: all install uninstall dist-version clean +.PHONY: .FORCE-GIT-VERSION-FILE +.PHONY: .FORCE-GIT-GUI-VARS diff --cc git-gui/git-gui.sh index f42e461fd,000000000..5d65272e2 mode 100755,000000..100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@@ -1,2869 -1,0 +1,2901 @@@ +#!/bin/sh +# Tcl ignores the next line -*- tcl -*- \ + if test "z$*" = zversion \ + || test "z$*" = z--version; \ + then \ + echo 'git-gui version @@GITGUI_VERSION@@'; \ + exit; \ + fi; \ + argv0=$0; \ + exec wish "$argv0" -- "$@" + +set appvers {@@GITGUI_VERSION@@} +set copyright [encoding convertfrom utf-8 { +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +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}] + +###################################################################### +## +## Tcl/Tk sanity check + +if {[catch {package require Tcl 8.4} err] + || [catch {package require Tk 8.4} err] +} { + catch {wm withdraw .} + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message $err + exit 1 +} + +catch {rename send {}} ; # What an evil concept... + +###################################################################### +## +## locate our library + +set oguilib {@@GITGUI_LIBDIR@@} +set oguirel {@@GITGUI_RELATIVE@@} +if {$oguirel eq {1}} { + set oguilib [file dirname [file dirname [file normalize $argv0]]] + set oguilib [file join $oguilib share git-gui lib] + set oguimsg [file join $oguilib msgs] +} elseif {[string match @@* $oguirel]} { + set oguilib [file join [file dirname [file normalize $argv0]] lib] + set oguimsg [file join [file dirname [file normalize $argv0]] po] +} else { + set oguimsg [file join $oguilib msgs] +} +unset oguirel + +###################################################################### +## +## enable verbose loading? + +if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} { + unset _verbose + rename auto_load real__auto_load + proc auto_load {name args} { + puts stderr "auto_load $name" + return [uplevel 1 real__auto_load $name $args] + } + rename source real__source + proc source {name} { + puts stderr "source $name" + uplevel 1 real__source $name + } +} + +###################################################################### +## +## Internationalization (i18n) through msgcat and gettext. See +## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html + +package require msgcat + +proc _mc_trim {fmt} { + set cmk [string first @@ $fmt] + if {$cmk > 0} { + return [string range $fmt 0 [expr {$cmk - 1}]] + } + return $fmt +} + +proc mc {en_fmt args} { + set fmt [_mc_trim [::msgcat::mc $en_fmt]] + if {[catch {set msg [eval [list format $fmt] $args]} err]} { + set msg [eval [list format [_mc_trim $en_fmt]] $args] + } + return $msg +} + +proc strcat {args} { + return [join $args {}] +} + +::msgcat::mcload $oguimsg +unset oguimsg + +###################################################################### +## +## read only globals + +set _appname {Git Gui} +set _gitdir {} +set _gitexec {} +set _reponame {} +set _iscygwin {} +set _search_path {} + +proc appname {} { + global _appname + return $_appname +} + +proc gitdir {args} { + global _gitdir + if {$args eq {}} { + return $_gitdir + } + return [eval [list file join $_gitdir] $args] +} + +proc gitexec {args} { + global _gitexec + if {$_gitexec eq {}} { + if {[catch {set _gitexec [git --exec-path]} err]} { + error "Git not installed?\n\n$err" + } + if {[is_Cygwin]} { + set _gitexec [exec cygpath \ + --windows \ + --absolute \ + $_gitexec] + } else { + set _gitexec [file normalize $_gitexec] + } + } + if {$args eq {}} { + return $_gitexec + } + return [eval [list file join $_gitexec] $args] +} + +proc reponame {} { + return $::_reponame +} + +proc is_MacOSX {} { + if {[tk windowingsystem] eq {aqua}} { + return 1 + } + return 0 +} + +proc is_Windows {} { + if {$::tcl_platform(platform) eq {windows}} { + return 1 + } + return 0 +} + +proc is_Cygwin {} { + global _iscygwin + if {$_iscygwin eq {}} { + if {$::tcl_platform(platform) eq {windows}} { + if {[catch {set p [exec cygpath --windir]} err]} { + set _iscygwin 0 + } else { + set _iscygwin 1 + } + } else { + set _iscygwin 0 + } + } + return $_iscygwin +} + +proc is_enabled {option} { + global enabled_options + if {[catch {set on $enabled_options($option)}]} {return 0} + return $on +} + +proc enable_option {option} { + global enabled_options + set enabled_options($option) 1 +} + +proc disable_option {option} { + global enabled_options + set enabled_options($option) 0 +} + +###################################################################### +## +## config + +proc is_many_config {name} { + switch -glob -- $name { + gui.recentrepo - + remote.*.fetch - + remote.*.push + {return 1} + * + {return 0} + } +} + +proc is_config_true {name} { + global repo_config + if {[catch {set v $repo_config($name)}]} { + return 0 + } elseif {$v eq {true} || $v eq {1} || $v eq {yes}} { + return 1 + } else { + return 0 + } +} + +proc get_config {name} { + global repo_config + if {[catch {set v $repo_config($name)}]} { + return {} + } else { + return $v + } +} + +###################################################################### +## +## handy utils + +proc _git_cmd {name} { + global _git_cmd_path + + if {[catch {set v $_git_cmd_path($name)}]} { + switch -- $name { + version - + --version - + --exec-path { return [list $::_git $name] } + } + + set p [gitexec git-$name$::_search_exe] + if {[file exists $p]} { + set v [list $p] + } elseif {[is_Windows] && [file exists [gitexec git-$name]]} { + # Try to determine what sort of magic will make + # git-$name go and do its thing, because native + # Tcl on Windows doesn't know it. + # + set p [gitexec git-$name] + set f [open $p r] + set s [gets $f] + close $f + + switch -glob -- [lindex $s 0] { + #!*sh { set i sh } + #!*perl { set i perl } + #!*python { set i python } + default { error "git-$name is not supported: $s" } + } + + upvar #0 _$i interp + if {![info exists interp]} { + set interp [_which $i] + } + if {$interp eq {}} { + error "git-$name requires $i (not in PATH)" + } + 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. + # + set v [list $::_git $name] + } + set _git_cmd_path($name) $v + } + return $v +} + +proc _which {what} { + global env _search_exe _search_path + + if {$_search_path eq {}} { + if {[is_Cygwin] && [regexp {^(/|\.:)} $env(PATH)]} { + set _search_path [split [exec cygpath \ + --windows \ + --path \ + --absolute \ + $env(PATH)] {;}] + set _search_exe .exe + } elseif {[is_Windows]} { + set gitguidir [file dirname [info script]] + regsub -all ";" $gitguidir "\\;" gitguidir + set env(PATH) "$gitguidir;$env(PATH)" + set _search_path [split $env(PATH) {;}] + set _search_exe .exe + } else { + set _search_path [split $env(PATH) :] + set _search_exe {} + } + } + + foreach p $_search_path { + set p [file join $p $what$_search_exe] + if {[file exists $p]} { + return [file normalize $p] + } + } + return {} +} + +proc _lappend_nice {cmd_var} { + global _nice + upvar $cmd_var cmd + + if {![info exists _nice]} { + set _nice [_which nice] + } + if {$_nice ne {}} { + lappend cmd $_nice + } +} + +proc git {args} { + set opt [list exec] + + while {1} { + switch -- [lindex $args 0] { + --nice { + _lappend_nice opt + } + + default { + break + } + + } + + set args [lrange $args 1 end] + } + + set cmdp [_git_cmd [lindex $args 0]] + set args [lrange $args 1 end] + + return [eval $opt $cmdp $args] +} + +proc _open_stdout_stderr {cmd} { + if {[catch { + set fd [open $cmd r] + } err]} { + if { [lindex $cmd end] eq {2>@1} + && $err eq {can not find channel named "1"} + } { + # Older versions of Tcl 8.4 don't have this 2>@1 IO + # redirect operator. Fallback to |& cat for those. + # The command was not actually started, so its safe + # to try to start it a second time. + # + set fd [open [concat \ + [lrange $cmd 0 end-1] \ + [list |& cat] \ + ] r] + } else { + error $err + } + } + fconfigure $fd -eofchar {} + return $fd +} + +proc git_read {args} { + set opt [list |] + + while {1} { + switch -- [lindex $args 0] { + --nice { + _lappend_nice opt + } + + --stderr { + lappend args 2>@1 + } + + default { + break + } + + } + + set args [lrange $args 1 end] + } + + set cmdp [_git_cmd [lindex $args 0]] + set args [lrange $args 1 end] + + return [_open_stdout_stderr [concat $opt $cmdp $args]] +} + +proc git_write {args} { + set opt [list |] + + while {1} { + switch -- [lindex $args 0] { + --nice { + _lappend_nice opt + } + + default { + break + } + + } + + set args [lrange $args 1 end] + } + + set cmdp [_git_cmd [lindex $args 0]] + set args [lrange $args 1 end] + + return [open [concat $opt $cmdp $args] w] +} + +proc githook_read {hook_name args} { + set pchook [gitdir hooks $hook_name] + lappend args 2>@1 + + # On Cygwin [file executable] might lie so we need to ask + # the shell if the hook is executable. Yes that's annoying. + # + if {[is_Cygwin]} { + upvar #0 _sh interp + if {![info exists interp]} { + set interp [_which sh] + } + if {$interp eq {}} { + error "hook execution requires sh (not in PATH)" + } + + set scr {if test -x "$1";then exec "$@";fi} + set sh_c [list | $interp -c $scr $interp $pchook] + return [_open_stdout_stderr [concat $sh_c $args]] + } + + if {[file executable $pchook]} { + return [_open_stdout_stderr [concat [list | $pchook] $args]] + } + + return {} +} + +proc sq {value} { + regsub -all ' $value "'\\''" value + return "'$value'" +} + +proc load_current_branch {} { + global current_branch is_detached + + set fd [open [gitdir HEAD] r] + if {[gets $fd ref] < 1} { + set ref {} + } + close $fd + + set pfx {ref: refs/heads/} + set len [string length $pfx] + if {[string equal -length $len $pfx $ref]} { + # We're on a branch. It might not exist. But + # HEAD looks good enough to be a branch. + # + set current_branch [string range $ref $len end] + set is_detached 0 + } else { + # Assume this is a detached head. + # + set current_branch HEAD + set is_detached 1 + } +} + +auto_load tk_optionMenu +rename tk_optionMenu real__tkOptionMenu +proc tk_optionMenu {w varName args} { + set m [eval real__tkOptionMenu $w $varName $args] + $m configure -font font_ui + $w configure -font font_ui + 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 break + return $text +} + +set root_exists 0 +bind . { + bind . {} + set root_exists 1 +} + +if {[is_Windows]} { + wm iconbitmap . -default $oguilib/git-gui.ico +} + +###################################################################### +## +## config defaults + +set cursor_ptr arrow +font create font_diff -family Courier -size 10 +font create font_ui +catch { + label .dummy + eval font configure font_ui [font actual [.dummy cget -font]] + destroy .dummy +} + +font create font_uiitalic +font create font_uibold +font create font_diffbold +font create font_diffitalic + +foreach class {Button Checkbutton Entry Label + Labelframe Listbox Menu Message + Radiobutton Spinbox Text} { + option add *$class.font font_ui +} +unset class + +if {[is_Windows] || [is_MacOSX]} { + option add *Menu.tearOff 0 +} + +if {[is_MacOSX]} { + set M1B M1 + set M1T Cmd +} else { + set M1B Control + set M1T Ctrl +} + +proc bind_button3 {w cmd} { + bind $w $cmd + if {[is_MacOSX]} { + # Mac OS X sends Button-2 on right click through three-button mouse, + # or through trackpad right-clicking (two-finger touch + click). + bind $w $cmd + bind $w $cmd + } +} + +proc apply_config {} { + global repo_config font_descs + + foreach option $font_descs { + set name [lindex $option 0] + set font [lindex $option 1] + if {[catch { + set need_weight 1 + foreach {cn cv} $repo_config(gui.$name) { + if {$cn eq {-weight}} { + set need_weight 0 + } + font configure $font $cn $cv + } + if {$need_weight} { + font configure $font -weight normal + } + } err]} { + error_popup [strcat [mc "Invalid font specified in %s:" "gui.$name"] "\n\n$err"] + } + foreach {cn cv} [font configure $font] { + font configure ${font}bold $cn $cv + font configure ${font}italic $cn $cv + } + font configure ${font}bold -weight bold + font configure ${font}italic -slant italic + } +} + +set default_config(merge.diffstat) true +set default_config(merge.summary) false +set default_config(merge.verbosity) 2 +set default_config(user.name) {} +set default_config(user.email) {} + +set default_config(gui.matchtrackingbranch) false +set default_config(gui.pruneduringfetch) false +set default_config(gui.trustmtime) false +set default_config(gui.diffcontext) 5 +set default_config(gui.newbranchtemplate) {} ++set default_config(gui.spellingdictionary) {} +set default_config(gui.fontui) [font configure font_ui] +set default_config(gui.fontdiff) [font configure font_diff] +set font_descs { + {fontui font_ui {mc "Main Font"}} + {fontdiff font_diff {mc "Diff/Console Font"}} +} + +###################################################################### +## +## find git + +set _git [_which git] +if {$_git eq {}} { + catch {wm withdraw .} + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message [mc "Cannot find git in PATH."] + exit 1 +} + +###################################################################### +## +## version check + +if {[catch {set _git_version [git --version]} err]} { + catch {wm withdraw .} + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message "Cannot determine Git version: + +$err + +[appname] requires Git 1.5.0 or later." + exit 1 +} +if {![regsub {^git version } $_git_version {} _git_version]} { + catch {wm withdraw .} + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message [strcat [mc "Cannot parse Git version string:"] "\n\n$_git_version"] + exit 1 +} + +set _real_git_version $_git_version +regsub -- {-dirty$} $_git_version {} _git_version +regsub {\.[0-9]+\.g[0-9a-f]+$} $_git_version {} _git_version +regsub {\.rc[0-9]+$} $_git_version {} _git_version +regsub {\.GIT$} $_git_version {} _git_version +regsub {\.[a-zA-Z]+\.[0-9]+$} $_git_version {} _git_version + +if {![regexp {^[1-9]+(\.[0-9]+)+$} $_git_version]} { + catch {wm withdraw .} + if {[tk_messageBox \ + -icon warning \ + -type yesno \ + -default no \ + -title "[appname]: warning" \ + -message [mc "Git version cannot be determined. + +%s claims it is version '%s'. + +%s requires at least Git 1.5.0 or later. + +Assume '%s' is version 1.5.0? +" $_git $_real_git_version [appname] $_real_git_version]] eq {yes}} { + set _git_version 1.5.0 + } else { + exit 1 + } +} +unset _real_git_version + +proc git-version {args} { + global _git_version + + switch [llength $args] { + 0 { + return $_git_version + } + + 2 { + set op [lindex $args 0] + set vr [lindex $args 1] + set cm [package vcompare $_git_version $vr] + return [expr $cm $op 0] + } + + 4 { + set type [lindex $args 0] + set name [lindex $args 1] + set parm [lindex $args 2] + set body [lindex $args 3] + + if {($type ne {proc} && $type ne {method})} { + error "Invalid arguments to git-version" + } + if {[llength $body] < 2 || [lindex $body end-1] ne {default}} { + error "Last arm of $type $name must be default" + } + + foreach {op vr cb} [lrange $body 0 end-2] { + if {[git-version $op $vr]} { + return [uplevel [list $type $name $parm $cb]] + } + } + + return [uplevel [list $type $name $parm [lindex $body end]]] + } + + default { + error "git-version >= x" + } + + } +} + +if {[git-version < 1.5]} { + catch {wm withdraw .} + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message "[appname] requires Git 1.5.0 or later. + +You are using [git-version]: + +[git --version]" + exit 1 +} + +###################################################################### +## +## configure our library + +set idx [file join $oguilib tclIndex] +if {[catch {set fd [open $idx r]} err]} { + catch {wm withdraw .} + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message $err + exit 1 +} +if {[gets $fd] eq {# Autogenerated by git-gui Makefile}} { + set idx [list] + while {[gets $fd n] >= 0} { + if {$n ne {} && ![string match #* $n]} { + lappend idx $n + } + } +} else { + set idx {} +} +close $fd + +if {$idx ne {}} { + set loaded [list] + foreach p $idx { + if {[lsearch -exact $loaded $p] >= 0} continue + source [file join $oguilib $p] + lappend loaded $p + } + unset loaded p +} else { + set auto_path [concat [list $oguilib] $auto_path] +} +unset -nocomplain idx fd + +###################################################################### +## +## config file parsing + +git-version proc _parse_config {arr_name args} { + >= 1.5.3 { + upvar $arr_name arr + array unset arr + set buf {} + catch { + set fd_rc [eval \ + [list git_read config] \ + $args \ + [list --null --list]] + fconfigure $fd_rc -translation binary + set buf [read $fd_rc] + close $fd_rc + } + foreach line [split $buf "\0"] { + if {[regexp {^([^\n]+)\n(.*)$} $line line name value]} { + if {[is_many_config $name]} { + lappend arr($name) $value + } else { + set arr($name) $value + } + } + } + } + default { + upvar $arr_name arr + array unset arr + catch { + set fd_rc [eval [list git_read config --list] $args] + while {[gets $fd_rc line] >= 0} { + if {[regexp {^([^=]+)=(.*)$} $line line name value]} { + if {[is_many_config $name]} { + lappend arr($name) $value + } else { + set arr($name) $value + } + } + } + close $fd_rc + } + } +} + +proc load_config {include_global} { + global repo_config global_config default_config + + if {$include_global} { + _parse_config global_config --global + } + _parse_config repo_config + + foreach name [array names default_config] { + if {[catch {set v $global_config($name)}]} { + set global_config($name) $default_config($name) + } + if {[catch {set v $repo_config($name)}]} { + set repo_config($name) $default_config($name) + } + } +} + +###################################################################### +## +## feature option selection + +if {[regexp {^git-(.+)$} [file tail $argv0] _junk subcommand]} { + unset _junk +} else { + set subcommand gui +} +if {$subcommand eq {gui.sh}} { + set subcommand gui +} +if {$subcommand eq {gui} && [llength $argv] > 0} { + set subcommand [lindex $argv 0] + set argv [lrange $argv 1 end] +} + +enable_option multicommit +enable_option branch +enable_option transport +disable_option bare + +switch -- $subcommand { +browser - +blame { + enable_option bare + + disable_option multicommit + disable_option branch + disable_option transport +} +citool { + enable_option singlecommit + + disable_option multicommit + disable_option branch + disable_option transport +} +} + +###################################################################### +## +## repository setup + +if {[catch { + set _gitdir $env(GIT_DIR) + set _prefix {} + }] + && [catch { + set _gitdir [git rev-parse --git-dir] + set _prefix [git rev-parse --show-prefix] + } err]} { + load_config 1 + apply_config + choose_repository::pick +} +if {![file isdirectory $_gitdir] && [is_Cygwin]} { + catch {set _gitdir [exec cygpath --windows $_gitdir]} +} +if {![file isdirectory $_gitdir]} { + catch {wm withdraw .} + error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"] + exit 1 +} +if {$_prefix ne {}} { + regsub -all {[^/]+/} $_prefix ../ cdup + if {[catch {cd $cdup} err]} { + catch {wm withdraw .} + error_popup [strcat [mc "Cannot move to top of working directory:"] "\n\n$err"] + exit 1 + } + unset cdup +} elseif {![is_enabled bare]} { + if {[lindex [file split $_gitdir] end] ne {.git}} { + catch {wm withdraw .} + error_popup [strcat [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"] + exit 1 + } + if {[catch {cd [file dirname $_gitdir]} err]} { + catch {wm withdraw .} + error_popup [strcat [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"] + exit 1 + } +} +set _reponame [file split [file normalize $_gitdir]] +if {[lindex $_reponame end] eq {.git}} { + set _reponame [lindex $_reponame end-1] +} else { + set _reponame [lindex $_reponame end] +} + +###################################################################### +## +## global init + +set current_diff_path {} +set current_diff_side {} +set diff_actions [list] + +set HEAD {} +set PARENT {} +set MERGE_HEAD [list] +set commit_type {} +set empty_tree {} +set current_branch {} +set is_detached 0 +set current_diff_path {} +set is_3way_diff 0 +set selected_commit_type new + +###################################################################### +## +## task management + +set rescan_active 0 +set diff_active 0 +set last_clicked {} + +set disable_on_lock [list] +set index_lock_type none + +proc lock_index {type} { + global index_lock_type disable_on_lock + + if {$index_lock_type eq {none}} { + set index_lock_type $type + foreach w $disable_on_lock { + uplevel #0 $w disabled + } + return 1 + } elseif {$index_lock_type eq "begin-$type"} { + set index_lock_type $type + return 1 + } + return 0 +} + +proc unlock_index {} { + global index_lock_type disable_on_lock + + set index_lock_type none + foreach w $disable_on_lock { + uplevel #0 $w normal + } +} + +###################################################################### +## +## status + +proc repository_state {ctvar hdvar mhvar} { + global current_branch + upvar $ctvar ct $hdvar hd $mhvar mh + + set mh [list] + + load_current_branch + if {[catch {set hd [git rev-parse --verify HEAD]}]} { + set hd {} + set ct initial + return + } + + set merge_head [gitdir MERGE_HEAD] + if {[file exists $merge_head]} { + set ct merge + set fd_mh [open $merge_head r] + while {[gets $fd_mh line] >= 0} { + lappend mh $line + } + close $fd_mh + return + } + + set ct normal +} + +proc PARENT {} { + global PARENT empty_tree + + set p [lindex $PARENT 0] + if {$p ne {}} { + return $p + } + if {$empty_tree eq {}} { + set empty_tree [git mktree << {}] + } + return $empty_tree +} + +proc rescan {after {honor_trustmtime 1}} { + global HEAD PARENT MERGE_HEAD commit_type + global ui_index ui_workdir ui_comm + global rescan_active file_states + global repo_config + + if {$rescan_active > 0 || ![lock_index read]} return + + repository_state newType newHEAD newMERGE_HEAD + if {[string match amend* $commit_type] + && $newType eq {normal} + && $newHEAD eq $HEAD} { + } else { + set HEAD $newHEAD + set PARENT $newHEAD + set MERGE_HEAD $newMERGE_HEAD + set commit_type $newType + } + + array unset file_states + + if {!$::GITGUI_BCK_exists && + (![$ui_comm edit modified] + || [string trim [$ui_comm get 0.0 end]] eq {})} { + if {[string match amend* $commit_type]} { + } elseif {[load_message GITGUI_MSG]} { + } elseif {[load_message MERGE_MSG]} { + } elseif {[load_message SQUASH_MSG]} { + } + $ui_comm edit reset + $ui_comm edit modified false + } + + if {$honor_trustmtime && $repo_config(gui.trustmtime) eq {true}} { + rescan_stage2 {} $after + } else { + set rescan_active 1 + ui_status [mc "Refreshing file status..."] + set fd_rf [git_read update-index \ + -q \ + --unmerged \ + --ignore-missing \ + --refresh \ + ] + fconfigure $fd_rf -blocking 0 -translation binary + fileevent $fd_rf readable \ + [list rescan_stage2 $fd_rf $after] + } +} + +if {[is_Cygwin]} { + set is_git_info_link {} + set is_git_info_exclude {} + proc have_info_exclude {} { + global is_git_info_link is_git_info_exclude + + if {$is_git_info_link eq {}} { + set is_git_info_link [file isfile [gitdir info.lnk]] + } + + if {$is_git_info_link} { + if {$is_git_info_exclude eq {}} { + if {[catch {exec test -f [gitdir info exclude]}]} { + set is_git_info_exclude 0 + } else { + set is_git_info_exclude 1 + } + } + return $is_git_info_exclude + } else { + return [file readable [gitdir info exclude]] + } + } +} else { + proc have_info_exclude {} { + return [file readable [gitdir info exclude]] + } +} + +proc rescan_stage2 {fd after} { + global rescan_active buf_rdi buf_rdf buf_rlo + + if {$fd ne {}} { + read $fd + if {![eof $fd]} return + close $fd + } + + set ls_others [list --exclude-per-directory=.gitignore] + if {[have_info_exclude]} { + lappend ls_others "--exclude-from=[gitdir info exclude]" + } + set user_exclude [get_config core.excludesfile] + if {$user_exclude ne {} && [file readable $user_exclude]} { + lappend ls_others "--exclude-from=$user_exclude" + } + + set buf_rdi {} + set buf_rdf {} + set buf_rlo {} + + set rescan_active 3 + ui_status [mc "Scanning for modified files ..."] + set fd_di [git_read diff-index --cached -z [PARENT]] + set fd_df [git_read diff-files -z] + set fd_lo [eval git_read ls-files --others -z $ls_others] + + fconfigure $fd_di -blocking 0 -translation binary -encoding binary + fconfigure $fd_df -blocking 0 -translation binary -encoding binary + fconfigure $fd_lo -blocking 0 -translation binary -encoding binary + fileevent $fd_di readable [list read_diff_index $fd_di $after] + fileevent $fd_df readable [list read_diff_files $fd_df $after] + fileevent $fd_lo readable [list read_ls_others $fd_lo $after] +} + +proc load_message {file} { + global ui_comm + + set f [gitdir $file] + if {[file isfile $f]} { + if {[catch {set fd [open $f r]}]} { + return 0 + } + fconfigure $fd -eofchar {} + set content [string trim [read $fd]] + close $fd + regsub -all -line {[ \r\t]+$} $content {} content + $ui_comm delete 0.0 end + $ui_comm insert end $content + return 1 + } + return 0 +} + +proc read_diff_index {fd after} { + global buf_rdi + + append buf_rdi [read $fd] + set c 0 + set n [string length $buf_rdi] + while {$c < $n} { + set z1 [string first "\0" $buf_rdi $c] + if {$z1 == -1} break + incr z1 + set z2 [string first "\0" $buf_rdi $z1] + if {$z2 == -1} break + + incr c + set i [split [string range $buf_rdi $c [expr {$z1 - 2}]] { }] + set p [string range $buf_rdi $z1 [expr {$z2 - 1}]] + merge_state \ + [encoding convertfrom $p] \ + [lindex $i 4]? \ + [list [lindex $i 0] [lindex $i 2]] \ + [list] + set c $z2 + incr c + } + if {$c < $n} { + set buf_rdi [string range $buf_rdi $c end] + } else { + set buf_rdi {} + } + + rescan_done $fd buf_rdi $after +} + +proc read_diff_files {fd after} { + global buf_rdf + + append buf_rdf [read $fd] + set c 0 + set n [string length $buf_rdf] + while {$c < $n} { + set z1 [string first "\0" $buf_rdf $c] + if {$z1 == -1} break + incr z1 + set z2 [string first "\0" $buf_rdf $z1] + if {$z2 == -1} break + + incr c + set i [split [string range $buf_rdf $c [expr {$z1 - 2}]] { }] + set p [string range $buf_rdf $z1 [expr {$z2 - 1}]] + merge_state \ + [encoding convertfrom $p] \ + ?[lindex $i 4] \ + [list] \ + [list [lindex $i 0] [lindex $i 2]] + set c $z2 + incr c + } + if {$c < $n} { + set buf_rdf [string range $buf_rdf $c end] + } else { + set buf_rdf {} + } + + rescan_done $fd buf_rdf $after +} + +proc read_ls_others {fd after} { + global buf_rlo + + append buf_rlo [read $fd] + set pck [split $buf_rlo "\0"] + set buf_rlo [lindex $pck end] + foreach p [lrange $pck 0 end-1] { + 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 +} + +proc rescan_done {fd buf after} { + global rescan_active current_diff_path + global file_states repo_config + upvar $buf to_clear + + if {![eof $fd]} return + set to_clear {} + close $fd + if {[incr rescan_active -1] > 0} return + + prune_selection + unlock_index + display_all_files + if {$current_diff_path ne {}} reshow_diff + uplevel #0 $after +} + +proc prune_selection {} { + global file_states selected_paths + + foreach path [array names selected_paths] { + if {[catch {set still_here $file_states($path)}]} { + unset selected_paths($path) + } + } +} + +###################################################################### +## +## ui helpers + +proc mapicon {w state path} { + global all_icons + + if {[catch {set r $all_icons($state$w)}]} { + puts "error: no icon for $w state={$state} $path" + return file_plain + } + return $r +} + +proc mapdesc {state path} { + global all_descs + + if {[catch {set r $all_descs($state)}]} { + puts "error: no desc for state={$state} $path" + return $state + } + return $r +} + +proc ui_status {msg} { + global main_status + if {[info exists main_status]} { + $main_status show $msg + } +} + +proc ui_ready {{test {}}} { + global main_status + if {[info exists main_status]} { + $main_status show [mc "Ready."] $test + } +} + +proc escape_path {path} { + regsub -all {\\} $path "\\\\" path + regsub -all "\n" $path "\\n" path + return $path +} + +proc short_path {path} { + return [escape_path [lindex [file split $path] end]] +} + +set next_icon_id 0 +set null_sha1 [string repeat 0 40] + +proc merge_state {path new_state {head_info {}} {index_info {}}} { + global file_states next_icon_id null_sha1 + + set s0 [string index $new_state 0] + set s1 [string index $new_state 1] + + if {[catch {set info $file_states($path)}]} { + set state __ + set icon n[incr next_icon_id] + } else { + set state [lindex $info 0] + set icon [lindex $info 1] + if {$head_info eq {}} {set head_info [lindex $info 2]} + if {$index_info eq {}} {set index_info [lindex $info 3]} + } + + if {$s0 eq {?}} {set s0 [string index $state 0]} \ + elseif {$s0 eq {_}} {set s0 _} + + if {$s1 eq {?}} {set s1 [string index $state 1]} \ + elseif {$s1 eq {_}} {set s1 _} + + if {$s0 eq {A} && $s1 eq {_} && $head_info eq {}} { + set head_info [list 0 $null_sha1] + } elseif {$s0 ne {_} && [string index $state 0] eq {_} + && $head_info eq {}} { + set head_info $index_info + } + + set file_states($path) [list $s0$s1 $icon \ + $head_info $index_info \ + ] + return $state +} + +proc display_file_helper {w path icon_name old_m new_m} { + global file_lists + + if {$new_m eq {_}} { + set lno [lsearch -sorted -exact $file_lists($w) $path] + if {$lno >= 0} { + set file_lists($w) [lreplace $file_lists($w) $lno $lno] + incr lno + $w conf -state normal + $w delete $lno.0 [expr {$lno + 1}].0 + $w conf -state disabled + } + } elseif {$old_m eq {_} && $new_m ne {_}} { + lappend file_lists($w) $path + set file_lists($w) [lsort -unique $file_lists($w)] + set lno [lsearch -sorted -exact $file_lists($w) $path] + incr lno + $w conf -state normal + $w image create $lno.0 \ + -align center -padx 5 -pady 1 \ + -name $icon_name \ + -image [mapicon $w $new_m $path] + $w insert $lno.1 "[escape_path $path]\n" + $w conf -state disabled + } elseif {$old_m ne $new_m} { + $w conf -state normal + $w image conf $icon_name -image [mapicon $w $new_m $path] + $w conf -state disabled + } +} + +proc display_file {path state} { + global file_states selected_paths + global ui_index ui_workdir + + set old_m [merge_state $path $state] + set s $file_states($path) + set new_m [lindex $s 0] + set icon_name [lindex $s 1] + + set o [string index $old_m 0] + set n [string index $new_m 0] + if {$o eq {U}} { + set o _ + } + if {$n eq {U}} { + set n _ + } + display_file_helper $ui_index $path $icon_name $o $n + + if {[string index $old_m 0] eq {U}} { + set o U + } else { + set o [string index $old_m 1] + } + if {[string index $new_m 0] eq {U}} { + set n U + } else { + set n [string index $new_m 1] + } + display_file_helper $ui_workdir $path $icon_name $o $n + + if {$new_m eq {__}} { + unset file_states($path) + catch {unset selected_paths($path)} + } +} + +proc display_all_files_helper {w path icon_name m} { + global file_lists + + lappend file_lists($w) $path + set lno [expr {[lindex [split [$w index end] .] 0] - 1}] + $w image create end \ + -align center -padx 5 -pady 1 \ + -name $icon_name \ + -image [mapicon $w $m $path] + $w insert end "[escape_path $path]\n" +} + +proc display_all_files {} { + global ui_index ui_workdir + global file_states file_lists + global last_clicked + + $ui_index conf -state normal + $ui_workdir conf -state normal + + $ui_index delete 0.0 end + $ui_workdir delete 0.0 end + set last_clicked {} + + set file_lists($ui_index) [list] + set file_lists($ui_workdir) [list] + + foreach path [lsort [array names file_states]] { + set s $file_states($path) + set m [lindex $s 0] + set icon_name [lindex $s 1] + + set s [string index $m 0] + if {$s ne {U} && $s ne {_}} { + display_all_files_helper $ui_index $path \ + $icon_name $s + } + + if {[string index $m 0] eq {U}} { + set s U + } else { + set s [string index $m 1] + } + if {$s ne {_}} { + display_all_files_helper $ui_workdir $path \ + $icon_name $s + } + } + + $ui_index conf -state disabled + $ui_workdir conf -state disabled +} + +###################################################################### +## +## icons + +set filemask { +#define mask_width 14 +#define mask_height 15 +static unsigned char mask_bits[] = { + 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, + 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, + 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f}; +} + +image create bitmap file_plain -background white -foreground black -data { +#define plain_width 14 +#define plain_height 15 +static unsigned char plain_bits[] = { + 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10, + 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, + 0x02, 0x10, 0x02, 0x10, 0xfe, 0x1f}; +} -maskdata $filemask + +image create bitmap file_mod -background white -foreground blue -data { +#define mod_width 14 +#define mod_height 15 +static unsigned char mod_bits[] = { + 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10, + 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10, + 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f}; +} -maskdata $filemask + +image create bitmap file_fulltick -background white -foreground "#007000" -data { +#define file_fulltick_width 14 +#define file_fulltick_height 15 +static unsigned char file_fulltick_bits[] = { + 0xfe, 0x01, 0x02, 0x1a, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x16, 0x02, 0x16, + 0x02, 0x13, 0x00, 0x13, 0x86, 0x11, 0x8c, 0x11, 0xd8, 0x10, 0xf2, 0x10, + 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f}; +} -maskdata $filemask + +image create bitmap file_parttick -background white -foreground "#005050" -data { +#define parttick_width 14 +#define parttick_height 15 +static unsigned char parttick_bits[] = { + 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10, + 0x7a, 0x14, 0x02, 0x16, 0x02, 0x13, 0x8a, 0x11, 0xda, 0x10, 0x72, 0x10, + 0x22, 0x10, 0x02, 0x10, 0xfe, 0x1f}; +} -maskdata $filemask + +image create bitmap file_question -background white -foreground black -data { +#define file_question_width 14 +#define file_question_height 15 +static unsigned char file_question_bits[] = { + 0xfe, 0x01, 0x02, 0x02, 0xe2, 0x04, 0xf2, 0x09, 0x1a, 0x1b, 0x0a, 0x13, + 0x82, 0x11, 0xc2, 0x10, 0x62, 0x10, 0x62, 0x10, 0x02, 0x10, 0x62, 0x10, + 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f}; +} -maskdata $filemask + +image create bitmap file_removed -background white -foreground red -data { +#define file_removed_width 14 +#define file_removed_height 15 +static unsigned char file_removed_bits[] = { + 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10, + 0x1a, 0x16, 0x32, 0x13, 0xe2, 0x11, 0xc2, 0x10, 0xe2, 0x11, 0x32, 0x13, + 0x1a, 0x16, 0x02, 0x10, 0xfe, 0x1f}; +} -maskdata $filemask + +image create bitmap file_merge -background white -foreground blue -data { +#define file_merge_width 14 +#define file_merge_height 15 +static unsigned char file_merge_bits[] = { + 0xfe, 0x01, 0x02, 0x03, 0x62, 0x05, 0x62, 0x09, 0x62, 0x1f, 0x62, 0x10, + 0xfa, 0x11, 0xf2, 0x10, 0x62, 0x10, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10, + 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f}; +} -maskdata $filemask + +set ui_index .vpane.files.index.list +set ui_workdir .vpane.files.workdir.list + +set all_icons(_$ui_index) file_plain +set all_icons(A$ui_index) file_fulltick +set all_icons(M$ui_index) file_fulltick +set all_icons(D$ui_index) file_removed +set all_icons(U$ui_index) file_merge + +set all_icons(_$ui_workdir) file_plain +set all_icons(M$ui_workdir) file_mod +set all_icons(D$ui_workdir) file_question +set all_icons(U$ui_workdir) file_merge +set all_icons(O$ui_workdir) file_plain + +set max_status_desc 0 +foreach i { + {__ {mc "Unmodified"}} + + {_M {mc "Modified, not staged"}} + {M_ {mc "Staged for commit"}} + {MM {mc "Portions staged for commit"}} + {MD {mc "Staged for commit, missing"}} + + {_O {mc "Untracked, not staged"}} + {A_ {mc "Staged for commit"}} + {AM {mc "Portions staged for commit"}} + {AD {mc "Staged for commit, missing"}} + + {_D {mc "Missing"}} + {D_ {mc "Staged for removal"}} + {DO {mc "Staged for removal, still present"}} + + {U_ {mc "Requires merge resolution"}} + {UU {mc "Requires merge resolution"}} + {UM {mc "Requires merge resolution"}} + {UD {mc "Requires merge resolution"}} + } { + set text [eval [lindex $i 1]] + if {$max_status_desc < [string length $text]} { + set max_status_desc [string length $text] + } + set all_descs([lindex $i 0]) $text +} +unset i + +###################################################################### +## +## util + +proc scrollbar2many {list mode args} { + foreach w $list {eval $w $mode $args} +} + +proc many2scrollbar {list mode sb top bottom} { + $sb set $top $bottom + foreach w $list {$w $mode moveto $top} +} + +proc incr_font_size {font {amt 1}} { + set sz [font configure $font -size] + incr sz $amt + font configure $font -size $sz + font configure ${font}bold -size $sz + font configure ${font}italic -size $sz +} + +###################################################################### +## +## ui commands + +set starting_gitk_msg [mc "Starting gitk... please wait..."] + +proc do_gitk {revs} { + # -- Always start gitk through whatever we were loaded with. This + # lets us bypass using shell process on Windows systems. + # + set exe [file join [file dirname $::_git] gitk] + set cmd [list [info nameofexecutable] $exe] + if {! [file exists $exe]} { + error_popup [mc "Unable to start gitk:\n\n%s does not exist" $exe] + } else { + global env + + if {[info exists env(GIT_DIR)]} { + set old_GIT_DIR $env(GIT_DIR) + } else { + set old_GIT_DIR {} + } + + set pwd [pwd] + cd [file dirname [gitdir]] + set env(GIT_DIR) [file tail [gitdir]] + + eval exec $cmd $revs & + + if {$old_GIT_DIR eq {}} { + unset env(GIT_DIR) + } else { + set env(GIT_DIR) $old_GIT_DIR + } + cd $pwd + + ui_status $::starting_gitk_msg + after 10000 { + ui_ready $starting_gitk_msg + } + } +} + +set is_quitting 0 + +proc do_quit {} { + global ui_comm is_quitting repo_config commit_type + global GITGUI_BCK_exists GITGUI_BCK_i ++ global ui_comm_spell + + if {$is_quitting} return + set is_quitting 1 + + if {[winfo exists $ui_comm]} { + # -- Stash our current commit buffer. + # + set save [gitdir GITGUI_MSG] + if {$GITGUI_BCK_exists && ![$ui_comm edit modified]} { + file rename -force [gitdir GITGUI_BCK] $save + set GITGUI_BCK_exists 0 + } else { + set msg [string trim [$ui_comm get 0.0 end]] + regsub -all -line {[ \r\t]+$} $msg {} msg + if {(![string match amend* $commit_type] + || [$ui_comm edit modified]) + && $msg ne {}} { + catch { + set fd [open $save w] + puts -nonewline $fd $msg + close $fd + } + } else { + catch {file delete $save} + } + } + ++ # -- Cancel our spellchecker if its running. ++ # ++ if {[info exists ui_comm_spell]} { ++ $ui_comm_spell stop ++ } ++ + # -- Remove our editor backup, its not needed. + # + after cancel $GITGUI_BCK_i + if {$GITGUI_BCK_exists} { + catch {file delete [gitdir GITGUI_BCK]} + } + + # -- Stash our current window geometry into this repository. + # + set cfg_geometry [list] + lappend cfg_geometry [wm geometry .] + lappend cfg_geometry [lindex [.vpane sash coord 0] 0] + lappend cfg_geometry [lindex [.vpane.files sash coord 0] 1] + if {[catch {set rc_geometry $repo_config(gui.geometry)}]} { + set rc_geometry {} + } + if {$cfg_geometry ne $rc_geometry} { + catch {git config gui.geometry $cfg_geometry} + } + } + + destroy . +} + +proc do_rescan {} { + rescan ui_ready +} + +proc do_commit {} { + commit_tree +} + +proc toggle_or_diff {w x y} { + global file_states file_lists current_diff_path ui_index ui_workdir + global last_clicked selected_paths + + set pos [split [$w index @$x,$y] .] + set lno [lindex $pos 0] + set col [lindex $pos 1] + set path [lindex $file_lists($w) [expr {$lno - 1}]] + if {$path eq {}} { + set last_clicked {} + return + } + + set last_clicked [list $w $lno] + array unset selected_paths + $ui_index tag remove in_sel 0.0 end + $ui_workdir tag remove in_sel 0.0 end + + if {$col == 0} { + if {$current_diff_path eq $path} { + set after {reshow_diff;} + } else { + set after {} + } + if {$w eq $ui_index} { + update_indexinfo \ + "Unstaging [short_path $path] from commit" \ + [list $path] \ + [concat $after [list ui_ready]] + } elseif {$w eq $ui_workdir} { + update_index \ + "Adding [short_path $path]" \ + [list $path] \ + [concat $after [list ui_ready]] + } + } else { + show_diff $path $w $lno + } +} + +proc add_one_to_selection {w x y} { + global file_lists last_clicked selected_paths + + set lno [lindex [split [$w index @$x,$y] .] 0] + set path [lindex $file_lists($w) [expr {$lno - 1}]] + if {$path eq {}} { + set last_clicked {} + return + } + + if {$last_clicked ne {} + && [lindex $last_clicked 0] ne $w} { + array unset selected_paths + [lindex $last_clicked 0] tag remove in_sel 0.0 end + } + + set last_clicked [list $w $lno] + if {[catch {set in_sel $selected_paths($path)}]} { + set in_sel 0 + } + if {$in_sel} { + unset selected_paths($path) + $w tag remove in_sel $lno.0 [expr {$lno + 1}].0 + } else { + set selected_paths($path) 1 + $w tag add in_sel $lno.0 [expr {$lno + 1}].0 + } +} + +proc add_range_to_selection {w x y} { + global file_lists last_clicked selected_paths + + if {[lindex $last_clicked 0] ne $w} { + toggle_or_diff $w $x $y + return + } + + set lno [lindex [split [$w index @$x,$y] .] 0] + set lc [lindex $last_clicked 1] + if {$lc < $lno} { + set begin $lc + set end $lno + } else { + set begin $lno + set end $lc + } + + foreach path [lrange $file_lists($w) \ + [expr {$begin - 1}] \ + [expr {$end - 1}]] { + set selected_paths($path) 1 + } + $w tag add in_sel $begin.0 [expr {$end + 1}].0 +} + +###################################################################### +## +## ui construction + +load_config 0 +apply_config +set ui_comm {} + +# -- Menu Bar +# +menu .mbar -tearoff 0 +.mbar add cascade -label [mc Repository] -menu .mbar.repository +.mbar add cascade -label [mc Edit] -menu .mbar.edit +if {[is_enabled branch]} { + .mbar add cascade -label [mc Branch] -menu .mbar.branch +} +if {[is_enabled multicommit] || [is_enabled singlecommit]} { + .mbar add cascade -label [mc Commit@@noun] -menu .mbar.commit +} +if {[is_enabled transport]} { + .mbar add cascade -label [mc Merge] -menu .mbar.merge + .mbar add cascade -label [mc Remote] -menu .mbar.remote +} +. configure -menu .mbar + +# -- Repository Menu +# +menu .mbar.repository + +.mbar.repository add command \ + -label [mc "Browse Current Branch's Files"] \ + -command {browser::new $current_branch} +set ui_browse_current [.mbar.repository index last] +.mbar.repository add command \ + -label [mc "Browse Branch Files..."] \ + -command browser_open::dialog +.mbar.repository add separator + +.mbar.repository add command \ + -label [mc "Visualize Current Branch's History"] \ + -command {do_gitk $current_branch} +set ui_visualize_current [.mbar.repository index last] +.mbar.repository add command \ + -label [mc "Visualize All Branch History"] \ + -command {do_gitk --all} +.mbar.repository add separator + +proc current_branch_write {args} { + global current_branch + .mbar.repository entryconf $::ui_browse_current \ + -label [mc "Browse %s's Files" $current_branch] + .mbar.repository entryconf $::ui_visualize_current \ + -label [mc "Visualize %s's History" $current_branch] +} +trace add variable current_branch write current_branch_write + +if {[is_enabled multicommit]} { + .mbar.repository add command -label [mc "Database Statistics"] \ + -command do_stats + + .mbar.repository add command -label [mc "Compress Database"] \ + -command do_gc + + .mbar.repository add command -label [mc "Verify Database"] \ + -command do_fsck_objects + + .mbar.repository add separator + + if {[is_Cygwin]} { + .mbar.repository add command \ + -label [mc "Create Desktop Icon"] \ + -command do_cygwin_shortcut + } elseif {[is_Windows]} { + .mbar.repository add command \ + -label [mc "Create Desktop Icon"] \ + -command do_windows_shortcut + } elseif {[is_MacOSX]} { + .mbar.repository add command \ + -label [mc "Create Desktop Icon"] \ + -command do_macosx_app + } +} + +.mbar.repository add command -label [mc Quit] \ + -command do_quit \ + -accelerator $M1T-Q + +# -- Edit Menu +# +menu .mbar.edit +.mbar.edit add command -label [mc Undo] \ + -command {catch {[focus] edit undo}} \ + -accelerator $M1T-Z +.mbar.edit add command -label [mc Redo] \ + -command {catch {[focus] edit redo}} \ + -accelerator $M1T-Y +.mbar.edit add separator +.mbar.edit add command -label [mc Cut] \ + -command {catch {tk_textCut [focus]}} \ + -accelerator $M1T-X +.mbar.edit add command -label [mc Copy] \ + -command {catch {tk_textCopy [focus]}} \ + -accelerator $M1T-C +.mbar.edit add command -label [mc Paste] \ + -command {catch {tk_textPaste [focus]; [focus] see insert}} \ + -accelerator $M1T-V +.mbar.edit add command -label [mc Delete] \ + -command {catch {[focus] delete sel.first sel.last}} \ + -accelerator Del +.mbar.edit add separator +.mbar.edit add command -label [mc "Select All"] \ + -command {catch {[focus] tag add sel 0.0 end}} \ + -accelerator $M1T-A + +# -- Branch Menu +# +if {[is_enabled branch]} { + menu .mbar.branch + + .mbar.branch add command -label [mc "Create..."] \ + -command branch_create::dialog \ + -accelerator $M1T-N + lappend disable_on_lock [list .mbar.branch entryconf \ + [.mbar.branch index last] -state] + + .mbar.branch add command -label [mc "Checkout..."] \ + -command branch_checkout::dialog \ + -accelerator $M1T-O + lappend disable_on_lock [list .mbar.branch entryconf \ + [.mbar.branch index last] -state] + + .mbar.branch add command -label [mc "Rename..."] \ + -command branch_rename::dialog + lappend disable_on_lock [list .mbar.branch entryconf \ + [.mbar.branch index last] -state] + + .mbar.branch add command -label [mc "Delete..."] \ + -command branch_delete::dialog + lappend disable_on_lock [list .mbar.branch entryconf \ + [.mbar.branch index last] -state] + + .mbar.branch add command -label [mc "Reset..."] \ + -command merge::reset_hard + lappend disable_on_lock [list .mbar.branch entryconf \ + [.mbar.branch index last] -state] +} + +# -- Commit Menu +# +if {[is_enabled multicommit] || [is_enabled singlecommit]} { + menu .mbar.commit + + .mbar.commit add radiobutton \ + -label [mc "New Commit"] \ + -command do_select_commit_type \ + -variable selected_commit_type \ + -value new + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + + .mbar.commit add radiobutton \ + -label [mc "Amend Last Commit"] \ + -command do_select_commit_type \ + -variable selected_commit_type \ + -value amend + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + + .mbar.commit add separator + + .mbar.commit add command -label [mc Rescan] \ + -command do_rescan \ + -accelerator F5 + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + + .mbar.commit add command -label [mc "Stage To Commit"] \ + -command do_add_selection \ + -accelerator $M1T-T + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + + .mbar.commit add command -label [mc "Stage Changed Files To Commit"] \ + -command do_add_all \ + -accelerator $M1T-I + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + + .mbar.commit add command -label [mc "Unstage From Commit"] \ + -command do_unstage_selection + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + + .mbar.commit add command -label [mc "Revert Changes"] \ + -command do_revert_selection + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] + + .mbar.commit add separator + + .mbar.commit add command -label [mc "Sign Off"] \ + -command do_signoff \ + -accelerator $M1T-S + + .mbar.commit add command -label [mc Commit@@verb] \ + -command do_commit \ + -accelerator $M1T-Return + lappend disable_on_lock \ + [list .mbar.commit entryconf [.mbar.commit index last] -state] +} + +# -- Merge Menu +# +if {[is_enabled branch]} { + menu .mbar.merge + .mbar.merge add command -label [mc "Local Merge..."] \ + -command merge::dialog \ + -accelerator $M1T-M + lappend disable_on_lock \ + [list .mbar.merge entryconf [.mbar.merge index last] -state] + .mbar.merge add command -label [mc "Abort Merge..."] \ + -command merge::reset_hard + lappend disable_on_lock \ + [list .mbar.merge entryconf [.mbar.merge index last] -state] +} + +# -- Transport Menu +# +if {[is_enabled transport]} { + menu .mbar.remote + + .mbar.remote add command \ + -label [mc "Push..."] \ + -command do_push_anywhere \ + -accelerator $M1T-P + .mbar.remote add command \ + -label [mc "Delete..."] \ + -command remote_branch_delete::dialog +} + +if {[is_MacOSX]} { + # -- Apple Menu (Mac OS X only) + # + .mbar add cascade -label [mc Apple] -menu .mbar.apple + menu .mbar.apple + + .mbar.apple add command -label [mc "About %s" [appname]] \ + -command do_about + .mbar.apple add separator + .mbar.apple add command \ + -label [mc "Preferences..."] \ + -command do_options \ + -accelerator $M1T-, + bind . <$M1B-,> do_options +} else { + # -- Edit Menu + # + .mbar.edit add separator + .mbar.edit add command -label [mc "Options..."] \ + -command do_options +} + +# -- Help Menu +# +.mbar add cascade -label [mc Help] -menu .mbar.help +menu .mbar.help + +if {![is_MacOSX]} { + .mbar.help add command -label [mc "About %s" [appname]] \ + -command do_about +} + +set browser {} +catch {set browser $repo_config(instaweb.browser)} +set doc_path [file dirname [gitexec]] +set doc_path [file join $doc_path Documentation index.html] + +if {[is_Cygwin]} { + set doc_path [exec cygpath --mixed $doc_path] +} + +if {$browser eq {}} { + if {[is_MacOSX]} { + set browser open + } elseif {[is_Cygwin]} { + set program_files [file dirname [exec cygpath --windir]] + set program_files [file join $program_files {Program Files}] + set firefox [file join $program_files {Mozilla Firefox} firefox.exe] + set ie [file join $program_files {Internet Explorer} IEXPLORE.EXE] + if {[file exists $firefox]} { + set browser $firefox + } elseif {[file exists $ie]} { + set browser $ie + } + unset program_files firefox ie + } +} + +if {[file isfile $doc_path]} { + set doc_url "file:$doc_path" +} else { + set doc_url {http://www.kernel.org/pub/software/scm/git/docs/} +} + +if {$browser ne {}} { + .mbar.help add command -label [mc "Online Documentation"] \ + -command [list exec $browser $doc_url &] +} +unset browser doc_path doc_url + +# -- Standard bindings +# +wm protocol . WM_DELETE_WINDOW do_quit +bind all <$M1B-Key-q> do_quit +bind all <$M1B-Key-Q> do_quit +bind all <$M1B-Key-w> {destroy [winfo toplevel %W]} +bind all <$M1B-Key-W> {destroy [winfo toplevel %W]} + +set subcommand_args {} +proc usage {} { + puts stderr "usage: $::argv0 $::subcommand $::subcommand_args" + exit 1 +} + +# -- Not a normal commit type invocation? Do that instead! +# +switch -- $subcommand { +browser - +blame { + set subcommand_args {rev? path} + if {$argv eq {}} usage + set head {} + set path {} + set is_path 0 + foreach a $argv { + if {$is_path || [file exists $_prefix$a]} { + if {$path ne {}} usage + set path $_prefix$a + break + } elseif {$a eq {--}} { + if {$path ne {}} { + if {$head ne {}} usage + set head $path + set path {} + } + set is_path 1 + } elseif {$head eq {}} { + if {$head ne {}} usage + set head $a + set is_path 1 + } else { + usage + } + } + unset is_path + + if {$head ne {} && $path eq {}} { + set path $_prefix$head + set head {} + } + + if {$head eq {}} { + load_current_branch + } else { + if {[regexp {^[0-9a-f]{1,39}$} $head]} { + if {[catch { + set head [git rev-parse --verify $head] + } err]} { + puts stderr $err + exit 1 + } + } + set current_branch $head + } + + switch -- $subcommand { + browser { + if {$head eq {}} { + if {$path ne {} && [file isdirectory $path]} { + set head $current_branch + } else { + set head $path + set path {} + } + } + browser::new $head $path + } + blame { + if {$head eq {} && ![file exists $path]} { + puts stderr [mc "fatal: cannot stat path %s: No such file or directory" $path] + exit 1 + } + blame::new $head $path + } + } + return +} +citool - +gui { + if {[llength $argv] != 0} { + puts -nonewline stderr "usage: $argv0" + if {$subcommand ne {gui} + && [file tail $argv0] ne "git-$subcommand"} { + puts -nonewline stderr " $subcommand" + } + puts stderr {} + exit 1 + } + # fall through to setup UI for commits +} +default { + puts stderr "usage: $argv0 \[{blame|browser|citool}\]" + exit 1 +} +} + +# -- Branch Control +# +frame .branch \ + -borderwidth 1 \ + -relief sunken +label .branch.l1 \ + -text [mc "Current Branch:"] \ + -anchor w \ + -justify left +label .branch.cb \ + -textvariable current_branch \ + -anchor w \ + -justify left +pack .branch.l1 -side left +pack .branch.cb -side left -fill x +pack .branch -side top -fill x + +# -- Main Window Layout +# +panedwindow .vpane -orient horizontal +panedwindow .vpane.files -orient vertical +.vpane add .vpane.files -sticky nsew -height 100 -width 200 +pack .vpane -anchor n -side top -fill both -expand 1 + +# -- Index File List +# +frame .vpane.files.index -height 100 -width 200 +label .vpane.files.index.title -text [mc "Staged Changes (Will Commit)"] \ + -background lightgreen +text $ui_index -background white -borderwidth 0 \ + -width 20 -height 10 \ + -wrap none \ + -cursor $cursor_ptr \ + -xscrollcommand {.vpane.files.index.sx set} \ + -yscrollcommand {.vpane.files.index.sy set} \ + -state disabled +scrollbar .vpane.files.index.sx -orient h -command [list $ui_index xview] +scrollbar .vpane.files.index.sy -orient v -command [list $ui_index yview] +pack .vpane.files.index.title -side top -fill x +pack .vpane.files.index.sx -side bottom -fill x +pack .vpane.files.index.sy -side right -fill y +pack $ui_index -side left -fill both -expand 1 + +# -- Working Directory File List +# +frame .vpane.files.workdir -height 100 -width 200 +label .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ + -background lightsalmon +text $ui_workdir -background white -borderwidth 0 \ + -width 20 -height 10 \ + -wrap none \ + -cursor $cursor_ptr \ + -xscrollcommand {.vpane.files.workdir.sx set} \ + -yscrollcommand {.vpane.files.workdir.sy set} \ + -state disabled +scrollbar .vpane.files.workdir.sx -orient h -command [list $ui_workdir xview] +scrollbar .vpane.files.workdir.sy -orient v -command [list $ui_workdir yview] +pack .vpane.files.workdir.title -side top -fill x +pack .vpane.files.workdir.sx -side bottom -fill x +pack .vpane.files.workdir.sy -side right -fill y +pack $ui_workdir -side left -fill both -expand 1 + +.vpane.files add .vpane.files.workdir -sticky nsew +.vpane.files add .vpane.files.index -sticky nsew + +foreach i [list $ui_index $ui_workdir] { + rmsel_tag $i + $i tag conf in_diff -background [$i tag cget in_sel -background] +} +unset i + +# -- Diff and Commit Area +# +frame .vpane.lower -height 300 -width 400 +frame .vpane.lower.commarea +frame .vpane.lower.diff -relief sunken -borderwidth 1 +pack .vpane.lower.diff -fill both -expand 1 +pack .vpane.lower.commarea -side bottom -fill x +.vpane add .vpane.lower -sticky nsew + +# -- Commit Area Buttons +# +frame .vpane.lower.commarea.buttons +label .vpane.lower.commarea.buttons.l -text {} \ + -anchor w \ + -justify left +pack .vpane.lower.commarea.buttons.l -side top -fill x +pack .vpane.lower.commarea.buttons -side left -fill y + +button .vpane.lower.commarea.buttons.rescan -text [mc Rescan] \ + -command do_rescan +pack .vpane.lower.commarea.buttons.rescan -side top -fill x +lappend disable_on_lock \ + {.vpane.lower.commarea.buttons.rescan conf -state} + +button .vpane.lower.commarea.buttons.incall -text [mc "Stage Changed"] \ + -command do_add_all +pack .vpane.lower.commarea.buttons.incall -side top -fill x +lappend disable_on_lock \ + {.vpane.lower.commarea.buttons.incall conf -state} + +button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \ + -command do_signoff +pack .vpane.lower.commarea.buttons.signoff -side top -fill x + +button .vpane.lower.commarea.buttons.commit -text [mc Commit@@verb] \ + -command do_commit +pack .vpane.lower.commarea.buttons.commit -side top -fill x +lappend disable_on_lock \ + {.vpane.lower.commarea.buttons.commit conf -state} + +button .vpane.lower.commarea.buttons.push -text [mc Push] \ + -command do_push_anywhere +pack .vpane.lower.commarea.buttons.push -side top -fill x + +# -- Commit Message Buffer +# +frame .vpane.lower.commarea.buffer +frame .vpane.lower.commarea.buffer.header +set ui_comm .vpane.lower.commarea.buffer.t +set ui_coml .vpane.lower.commarea.buffer.header.l +radiobutton .vpane.lower.commarea.buffer.header.new \ + -text [mc "New Commit"] \ + -command do_select_commit_type \ + -variable selected_commit_type \ + -value new +lappend disable_on_lock \ + [list .vpane.lower.commarea.buffer.header.new conf -state] +radiobutton .vpane.lower.commarea.buffer.header.amend \ + -text [mc "Amend Last Commit"] \ + -command do_select_commit_type \ + -variable selected_commit_type \ + -value amend +lappend disable_on_lock \ + [list .vpane.lower.commarea.buffer.header.amend conf -state] +label $ui_coml \ + -anchor w \ + -justify left +proc trace_commit_type {varname args} { + global ui_coml commit_type + switch -glob -- $commit_type { + initial {set txt [mc "Initial Commit Message:"]} + amend {set txt [mc "Amended Commit Message:"]} + amend-initial {set txt [mc "Amended Initial Commit Message:"]} + amend-merge {set txt [mc "Amended Merge Commit Message:"]} + merge {set txt [mc "Merge Commit Message:"]} + * {set txt [mc "Commit Message:"]} + } + $ui_coml conf -text $txt +} +trace add variable commit_type write trace_commit_type +pack $ui_coml -side left -fill x +pack .vpane.lower.commarea.buffer.header.amend -side right +pack .vpane.lower.commarea.buffer.header.new -side right + +text $ui_comm -background white -borderwidth 1 \ + -undo true \ + -maxundo 20 \ + -autoseparators true \ + -relief sunken \ + -width 75 -height 9 -wrap none \ + -font font_diff \ + -yscrollcommand {.vpane.lower.commarea.buffer.sby set} +scrollbar .vpane.lower.commarea.buffer.sby \ + -command [list $ui_comm yview] +pack .vpane.lower.commarea.buffer.header -side top -fill x +pack .vpane.lower.commarea.buffer.sby -side right -fill y +pack $ui_comm -side left -fill y +pack .vpane.lower.commarea.buffer -side left -fill y + +# -- Commit Message Buffer Context Menu +# +set ctxm .vpane.lower.commarea.buffer.ctxm +menu $ctxm -tearoff 0 +$ctxm add command \ + -label [mc Cut] \ + -command {tk_textCut $ui_comm} +$ctxm add command \ + -label [mc Copy] \ + -command {tk_textCopy $ui_comm} +$ctxm add command \ + -label [mc Paste] \ + -command {tk_textPaste $ui_comm} +$ctxm add command \ + -label [mc Delete] \ + -command {$ui_comm delete sel.first sel.last} +$ctxm add separator +$ctxm add command \ + -label [mc "Select All"] \ + -command {focus $ui_comm;$ui_comm tag add sel 0.0 end} +$ctxm add command \ + -label [mc "Copy All"] \ + -command { + $ui_comm tag add sel 0.0 end + tk_textCopy $ui_comm + $ui_comm tag remove sel 0.0 end + } +$ctxm add separator +$ctxm add command \ + -label [mc "Sign Off"] \ + -command do_signoff - bind_button3 $ui_comm "tk_popup $ctxm %X %Y" ++set ui_comm_ctxm $ctxm + +# -- Diff Header +# +proc trace_current_diff_path {varname args} { + global current_diff_path diff_actions file_states + if {$current_diff_path eq {}} { + set s {} + set f {} + set p {} + set o disabled + } else { + set p $current_diff_path + set s [mapdesc [lindex $file_states($p) 0] $p] + set f [mc "File:"] + set p [escape_path $p] + set o normal + } + + .vpane.lower.diff.header.status configure -text $s + .vpane.lower.diff.header.file configure -text $f + .vpane.lower.diff.header.path configure -text $p + foreach w $diff_actions { + uplevel #0 $w $o + } +} +trace add variable current_diff_path write trace_current_diff_path + +frame .vpane.lower.diff.header -background gold +label .vpane.lower.diff.header.status \ + -background gold \ + -width $max_status_desc \ + -anchor w \ + -justify left +label .vpane.lower.diff.header.file \ + -background gold \ + -anchor w \ + -justify left +label .vpane.lower.diff.header.path \ + -background gold \ + -anchor w \ + -justify left +pack .vpane.lower.diff.header.status -side left +pack .vpane.lower.diff.header.file -side left +pack .vpane.lower.diff.header.path -fill x +set ctxm .vpane.lower.diff.header.ctxm +menu $ctxm -tearoff 0 +$ctxm add command \ + -label [mc Copy] \ + -command { + clipboard clear + clipboard append \ + -format STRING \ + -type STRING \ + -- $current_diff_path + } +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +bind_button3 .vpane.lower.diff.header.path "tk_popup $ctxm %X %Y" + +# -- Diff Body +# +frame .vpane.lower.diff.body +set ui_diff .vpane.lower.diff.body.t +text $ui_diff -background white -borderwidth 0 \ + -width 80 -height 15 -wrap none \ + -font font_diff \ + -xscrollcommand {.vpane.lower.diff.body.sbx set} \ + -yscrollcommand {.vpane.lower.diff.body.sby set} \ + -state disabled +scrollbar .vpane.lower.diff.body.sbx -orient horizontal \ + -command [list $ui_diff xview] +scrollbar .vpane.lower.diff.body.sby -orient vertical \ + -command [list $ui_diff yview] +pack .vpane.lower.diff.body.sbx -side bottom -fill x +pack .vpane.lower.diff.body.sby -side right -fill y +pack $ui_diff -side left -fill both -expand 1 +pack .vpane.lower.diff.header -side top -fill x +pack .vpane.lower.diff.body -side bottom -fill both -expand 1 + +$ui_diff tag conf d_cr -elide true +$ui_diff tag conf d_@ -foreground blue -font font_diffbold +$ui_diff tag conf d_+ -foreground {#00a000} +$ui_diff tag conf d_- -foreground red + +$ui_diff tag conf d_++ -foreground {#00a000} +$ui_diff tag conf d_-- -foreground red +$ui_diff tag conf d_+s \ + -foreground {#00a000} \ + -background {#e2effa} +$ui_diff tag conf d_-s \ + -foreground red \ + -background {#e2effa} +$ui_diff tag conf d_s+ \ + -foreground {#00a000} \ + -background ivory1 +$ui_diff tag conf d_s- \ + -foreground red \ + -background ivory1 + +$ui_diff tag conf d<<<<<<< \ + -foreground orange \ + -font font_diffbold +$ui_diff tag conf d======= \ + -foreground orange \ + -font font_diffbold +$ui_diff tag conf d>>>>>>> \ + -foreground orange \ + -font font_diffbold + +$ui_diff tag raise sel + +# -- Diff Body Context Menu +# +set ctxm .vpane.lower.diff.body.ctxm +menu $ctxm -tearoff 0 +$ctxm add command \ + -label [mc "Apply/Reverse Hunk"] \ + -command {apply_hunk $cursorX $cursorY} +set ui_diff_applyhunk [$ctxm index last] +lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state] +$ctxm add separator +$ctxm add command \ + -label [mc "Show Less Context"] \ + -command {if {$repo_config(gui.diffcontext) >= 1} { + incr repo_config(gui.diffcontext) -1 + reshow_diff + }} +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add command \ + -label [mc "Show More Context"] \ + -command {if {$repo_config(gui.diffcontext) < 99} { + incr repo_config(gui.diffcontext) + reshow_diff + }} +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add separator +$ctxm add command \ + -label [mc Refresh] \ + -command reshow_diff +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add command \ + -label [mc Copy] \ + -command {tk_textCopy $ui_diff} +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add command \ + -label [mc "Select All"] \ + -command {focus $ui_diff;$ui_diff tag add sel 0.0 end} +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add command \ + -label [mc "Copy All"] \ + -command { + $ui_diff tag add sel 0.0 end + tk_textCopy $ui_diff + $ui_diff tag remove sel 0.0 end + } +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add separator +$ctxm add command \ + -label [mc "Decrease Font Size"] \ + -command {incr_font_size font_diff -1} +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add command \ + -label [mc "Increase Font Size"] \ + -command {incr_font_size font_diff 1} +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add separator +$ctxm add command -label [mc "Options..."] \ + -command do_options +proc popup_diff_menu {ctxm x y X Y} { + global current_diff_path file_states + set ::cursorX $x + set ::cursorY $y + if {$::ui_index eq $::current_diff_side} { + set l [mc "Unstage Hunk From Commit"] + } else { + set l [mc "Stage Hunk For Commit"] + } + 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 +} +bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y] + +# -- Status Bar +# +set main_status [::status_bar::new .status] +pack .status -anchor w -side bottom -fill x +$main_status show [mc "Initializing..."] + +# -- Load geometry +# +catch { +set gm $repo_config(gui.geometry) +wm geometry . [lindex $gm 0] +.vpane sash place 0 \ + [lindex $gm 1] \ + [lindex [.vpane sash coord 0] 1] +.vpane.files sash place 0 \ + [lindex [.vpane.files sash coord 0] 0] \ + [lindex $gm 2] +unset gm +} + +# -- Key Bindings +# +bind $ui_comm <$M1B-Key-Return> {do_commit;break} +bind $ui_comm <$M1B-Key-t> {do_add_selection;break} +bind $ui_comm <$M1B-Key-T> {do_add_selection;break} +bind $ui_comm <$M1B-Key-i> {do_add_all;break} +bind $ui_comm <$M1B-Key-I> {do_add_all;break} +bind $ui_comm <$M1B-Key-x> {tk_textCut %W;break} +bind $ui_comm <$M1B-Key-X> {tk_textCut %W;break} +bind $ui_comm <$M1B-Key-c> {tk_textCopy %W;break} +bind $ui_comm <$M1B-Key-C> {tk_textCopy %W;break} +bind $ui_comm <$M1B-Key-v> {tk_textPaste %W; %W see insert; break} +bind $ui_comm <$M1B-Key-V> {tk_textPaste %W; %W see insert; break} +bind $ui_comm <$M1B-Key-a> {%W tag add sel 0.0 end;break} +bind $ui_comm <$M1B-Key-A> {%W tag add sel 0.0 end;break} + +bind $ui_diff <$M1B-Key-x> {tk_textCopy %W;break} +bind $ui_diff <$M1B-Key-X> {tk_textCopy %W;break} +bind $ui_diff <$M1B-Key-c> {tk_textCopy %W;break} +bind $ui_diff <$M1B-Key-C> {tk_textCopy %W;break} +bind $ui_diff <$M1B-Key-v> {break} +bind $ui_diff <$M1B-Key-V> {break} +bind $ui_diff <$M1B-Key-a> {%W tag add sel 0.0 end;break} +bind $ui_diff <$M1B-Key-A> {%W tag add sel 0.0 end;break} +bind $ui_diff {catch {%W yview scroll -1 units};break} +bind $ui_diff {catch {%W yview scroll 1 units};break} +bind $ui_diff {catch {%W xview scroll -1 units};break} +bind $ui_diff {catch {%W xview scroll 1 units};break} +bind $ui_diff {catch {%W yview scroll -1 units};break} +bind $ui_diff {catch {%W yview scroll 1 units};break} +bind $ui_diff {catch {%W xview scroll -1 units};break} +bind $ui_diff {catch {%W xview scroll 1 units};break} +bind $ui_diff {catch {%W yview scroll -1 pages};break} +bind $ui_diff {catch {%W yview scroll 1 pages};break} +bind $ui_diff {focus %W} + +if {[is_enabled branch]} { + bind . <$M1B-Key-n> branch_create::dialog + bind . <$M1B-Key-N> branch_create::dialog + bind . <$M1B-Key-o> branch_checkout::dialog + bind . <$M1B-Key-O> branch_checkout::dialog + bind . <$M1B-Key-m> merge::dialog + bind . <$M1B-Key-M> merge::dialog +} +if {[is_enabled transport]} { + bind . <$M1B-Key-p> do_push_anywhere + bind . <$M1B-Key-P> do_push_anywhere +} + +bind . do_rescan +bind . <$M1B-Key-r> do_rescan +bind . <$M1B-Key-R> do_rescan +bind . <$M1B-Key-s> do_signoff +bind . <$M1B-Key-S> do_signoff +bind . <$M1B-Key-t> do_add_selection +bind . <$M1B-Key-T> do_add_selection +bind . <$M1B-Key-i> do_add_all +bind . <$M1B-Key-I> do_add_all +bind . <$M1B-Key-Return> do_commit +foreach i [list $ui_index $ui_workdir] { + bind $i "toggle_or_diff $i %x %y; break" + bind $i <$M1B-Button-1> "add_one_to_selection $i %x %y; break" + bind $i "add_range_to_selection $i %x %y; break" +} +unset i + +set file_lists($ui_index) [list] +set file_lists($ui_workdir) [list] + +wm title . "[appname] ([reponame]) [file normalize [file dirname [gitdir]]]" +focus -force $ui_comm + +# -- Warn the user about environmental problems. Cygwin's Tcl +# does *not* pass its env array onto any processes it spawns. +# This means that git processes get none of our environment. +# +if {[is_Cygwin]} { + set ignored_env 0 + set suggest_user {} + set msg [mc "Possible environment issues exist. + +The following environment variables are probably +going to be ignored by any Git subprocess run +by %s: + +" [appname]] + foreach name [array names env] { + switch -regexp -- $name { + {^GIT_INDEX_FILE$} - + {^GIT_OBJECT_DIRECTORY$} - + {^GIT_ALTERNATE_OBJECT_DIRECTORIES$} - + {^GIT_DIFF_OPTS$} - + {^GIT_EXTERNAL_DIFF$} - + {^GIT_PAGER$} - + {^GIT_TRACE$} - + {^GIT_CONFIG$} - + {^GIT_CONFIG_LOCAL$} - + {^GIT_(AUTHOR|COMMITTER)_DATE$} { + append msg " - $name\n" + incr ignored_env + } + {^GIT_(AUTHOR|COMMITTER)_(NAME|EMAIL)$} { + append msg " - $name\n" + incr ignored_env + set suggest_user $name + } + } + } + if {$ignored_env > 0} { + append msg [mc " +This is due to a known issue with the +Tcl binary distributed by Cygwin."] + + if {$suggest_user ne {}} { + append msg [mc " + +A good replacement for %s +is placing values for the user.name and +user.email settings into your personal +~/.gitconfig file. +" $suggest_user] + } + warn_popup $msg + } + unset ignored_env msg suggest_user name +} + +# -- Only initialize complex UI if we are going to stay running. +# +if {[is_enabled transport]} { + load_all_remotes + + set n [.mbar.remote index end] + populate_push_menu + populate_fetch_menu + set n [expr {[.mbar.remote index end] - $n}] + if {$n > 0} { + .mbar.remote insert $n separator + } + unset n +} + +if {[winfo exists $ui_comm]} { + set GITGUI_BCK_exists [load_message GITGUI_BCK] + + # -- If both our backup and message files exist use the + # newer of the two files to initialize the buffer. + # + if {$GITGUI_BCK_exists} { + set m [gitdir GITGUI_MSG] + if {[file isfile $m]} { + if {[file mtime [gitdir GITGUI_BCK]] > [file mtime $m]} { + catch {file delete [gitdir GITGUI_MSG]} + } else { + $ui_comm delete 0.0 end + $ui_comm edit reset + $ui_comm edit modified false + catch {file delete [gitdir GITGUI_BCK]} + set GITGUI_BCK_exists 0 + } + } + unset m + } + + proc backup_commit_buffer {} { + global ui_comm GITGUI_BCK_exists + + set m [$ui_comm edit modified] + if {$m || $GITGUI_BCK_exists} { + set msg [string trim [$ui_comm get 0.0 end]] + regsub -all -line {[ \r\t]+$} $msg {} msg + + if {$msg eq {}} { + if {$GITGUI_BCK_exists} { + catch {file delete [gitdir GITGUI_BCK]} + set GITGUI_BCK_exists 0 + } + } elseif {$m} { + catch { + set fd [open [gitdir GITGUI_BCK] w] + puts -nonewline $fd $msg + close $fd + set GITGUI_BCK_exists 1 + } + } + + $ui_comm edit modified false + } + + set ::GITGUI_BCK_i [after 2000 backup_commit_buffer] + } + + backup_commit_buffer ++ ++ # -- If the user has aspell available we can drive it ++ # in pipe mode to spellcheck the commit message. ++ # ++ set spell_cmd [list |] ++ set spell_dict [get_config gui.spellingdictionary] ++ lappend spell_cmd aspell ++ if {$spell_dict ne {}} { ++ lappend spell_cmd --master=$spell_dict ++ } ++ lappend spell_cmd --mode=none ++ lappend spell_cmd --encoding=utf-8 ++ lappend spell_cmd pipe ++ if {$spell_dict eq {none} ++ || [catch {set spell_fd [open $spell_cmd r+]} spell_err]} { ++ bind_button3 $ui_comm [list tk_popup $ui_comm_ctxm %X %Y] ++ } else { ++ set ui_comm_spell [spellcheck::init \ ++ $spell_fd \ ++ $ui_comm \ ++ $ui_comm_ctxm \ ++ ] ++ } ++ unset -nocomplain spell_cmd spell_fd spell_err spell_dict +} + +lock_index begin-read +if {![winfo ismapped .]} { + wm deiconify . +} +after 1 do_rescan +if {[is_enabled multicommit]} { + after 1000 hint_gc +} diff --cc git-gui/lib/about.tcl index 719fc547b,000000000..47be8eb97 mode 100644,000000..100644 --- a/git-gui/lib/about.tcl +++ b/git-gui/lib/about.tcl @@@ -1,81 -1,0 +1,86 @@@ +# git-gui about git-gui dialog +# Copyright (C) 2006, 2007 Shawn Pearce + +proc do_about {} { + global appvers copyright oguilib + global tcl_patchLevel tk_patchLevel ++ global ui_comm_spell + + set w .about_dialog + toplevel $w + wm geometry $w "+[winfo rootx .]+[winfo rooty .]" + + pack [git_logo $w.git_logo] -side left -fill y -padx 10 -pady 10 + label $w.header -text [mc "About %s" [appname]] \ + -font font_uibold + pack $w.header -side top -fill x + + frame $w.buttons + button $w.buttons.close -text {Close} \ + -default active \ + -command [list destroy $w] + pack $w.buttons.close -side right + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + label $w.desc \ + -text "[mc "git-gui - a graphical user interface for Git."]\n$copyright" \ + -padx 5 -pady 5 \ + -justify left \ + -anchor w \ + -borderwidth 1 \ + -relief solid + pack $w.desc -side top -fill x -padx 5 -pady 5 + + set v {} + append v "git-gui version $appvers\n" + append v "[git version]\n" + append v "\n" + if {$tcl_patchLevel eq $tk_patchLevel} { + append v "Tcl/Tk version $tcl_patchLevel" + } else { + append v "Tcl version $tcl_patchLevel" + append v ", Tk version $tk_patchLevel" + } ++ if {[info exists ui_comm_spell]} { ++ append v "\n" ++ append v [$ui_comm_spell version] ++ } + + set d {} + append d "git wrapper: $::_git\n" + append d "git exec dir: [gitexec]\n" + append d "git-gui lib: $oguilib" + + label $w.vers \ + -text $v \ + -padx 5 -pady 5 \ + -justify left \ + -anchor w \ + -borderwidth 1 \ + -relief solid + pack $w.vers -side top -fill x -padx 5 -pady 5 + + label $w.dirs \ + -text $d \ + -padx 5 -pady 5 \ + -justify left \ + -anchor w \ + -borderwidth 1 \ + -relief solid + pack $w.dirs -side top -fill x -padx 5 -pady 5 + + menu $w.ctxm -tearoff 0 + $w.ctxm add command \ + -label {Copy} \ + -command " + clipboard clear + clipboard append -format STRING -type STRING -- \[$w.vers cget -text\] + " + + bind $w "grab $w; focus $w.buttons.close" + bind $w "destroy $w" + bind $w "destroy $w" + bind_button3 $w.vers "tk_popup $w.ctxm %X %Y; grab $w; focus $w" + wm title $w "About [appname]" + tkwait window $w +} diff --cc git-gui/lib/checkout_op.tcl index f24396692,000000000..6e1411711 mode 100644,000000..100644 --- a/git-gui/lib/checkout_op.tcl +++ b/git-gui/lib/checkout_op.tcl @@@ -1,588 -1,0 +1,588 @@@ +# git-gui commit checkout support +# Copyright (C) 2007 Shawn Pearce + +class checkout_op { + +field w {}; # our window (if we have one) +field w_cons {}; # embedded console window object + +field new_expr ; # expression the user saw/thinks this is +field new_hash ; # commit SHA-1 we are switching to +field new_ref ; # ref we are updating/creating + +field parent_w .; # window that started us +field merge_type none; # type of merge to apply to existing branch +field merge_base {}; # merge base if we have another ref involved +field fetch_spec {}; # refetch tracking branch if used? +field checkout 1; # actually checkout the branch? +field create 0; # create the branch if it doesn't exist? + +field reset_ok 0; # did the user agree to reset? +field fetch_ok 0; # did the fetch succeed? + +field readtree_d {}; # buffered output from read-tree +field update_old {}; # was the update-ref call deferred? +field reflog_msg {}; # log message for the update-ref call + +constructor new {expr hash {ref {}}} { + set new_expr $expr + set new_hash $hash + set new_ref $ref + + return $this +} + +method parent {path} { + set parent_w [winfo toplevel $path] +} + +method enable_merge {type} { + set merge_type $type +} + +method enable_fetch {spec} { + set fetch_spec $spec +} + +method enable_checkout {co} { + set checkout $co +} + +method enable_create {co} { + set create $co +} + +method run {} { + if {$fetch_spec ne {}} { + global M1B + + # We were asked to refresh a single tracking branch + # before we get to work. We should do that before we + # consider any ref updating. + # + set fetch_ok 0 + set l_trck [lindex $fetch_spec 0] + set remote [lindex $fetch_spec 1] + set r_head [lindex $fetch_spec 2] + regsub ^refs/heads/ $r_head {} r_name + + set cmd [list git fetch $remote] + if {$l_trck ne {}} { + lappend cmd +$r_head:$l_trck + } else { + lappend cmd $r_head + } + + _toplevel $this {Refreshing Tracking Branch} + set w_cons [::console::embed \ + $w.console \ + [mc "Fetching %s from %s" $r_name $remote]] + pack $w.console -fill both -expand 1 + $w_cons exec $cmd [cb _finish_fetch] + + bind $w <$M1B-Key-w> break + bind $w <$M1B-Key-W> break + bind $w " + [list grab $w] + [list focus $w] + " + wm protocol $w WM_DELETE_WINDOW [cb _noop] + tkwait window $w + + if {!$fetch_ok} { + delete_this + return 0 + } + } + + if {$new_ref ne {}} { + # If we have a ref we need to update it before we can + # proceed with a checkout (if one was enabled). + # + if {![_update_ref $this]} { + delete_this + return 0 + } + } + + if {$checkout} { + _checkout $this + return 1 + } + + delete_this + return 1 +} + +method _noop {} {} + +method _finish_fetch {ok} { + if {$ok} { + set l_trck [lindex $fetch_spec 0] + if {$l_trck eq {}} { + set l_trck FETCH_HEAD + } + if {[catch {set new_hash [git rev-parse --verify "$l_trck^0"]} err]} { + set ok 0 + $w_cons insert [mc "fatal: Cannot resolve %s" $l_trck] + $w_cons insert $err + } + } + + $w_cons done $ok + set w_cons {} + wm protocol $w WM_DELETE_WINDOW {} + + if {$ok} { + destroy $w + set w {} + } else { + button $w.close -text [mc Close] -command [list destroy $w] + pack $w.close -side bottom -anchor e -padx 10 -pady 10 + } + + set fetch_ok $ok +} + +method _update_ref {} { + global null_sha1 current_branch + + set ref $new_ref + set new $new_hash + + set is_current 0 + set rh refs/heads/ + set rn [string length $rh] + if {[string equal -length $rn $rh $ref]} { + set newbranch [string range $ref $rn end] + if {$current_branch eq $newbranch} { + set is_current 1 + } + } else { + set newbranch $ref + } + + if {[catch {set cur [git rev-parse --verify "$ref^0"]}]} { + # Assume it does not exist, and that is what the error was. + # + if {!$create} { + _error $this [mc "Branch '%s' does not exist." $newbranch] + return 0 + } + + set reflog_msg "branch: Created from $new_expr" + set cur $null_sha1 + } elseif {$create && $merge_type eq {none}} { + # We were told to create it, but not do a merge. + # Bad. Name shouldn't have existed. + # + _error $this [mc "Branch '%s' already exists." $newbranch] + return 0 + } elseif {!$create && $merge_type eq {none}} { + # We aren't creating, it exists and we don't merge. + # We are probably just a simple branch switch. + # Use whatever value we just read. + # + set new $cur + set new_hash $cur + } elseif {$new eq $cur} { + # No merge would be required, don't compute anything. + # + } else { + catch {set merge_base [git merge-base $new $cur]} + if {$merge_base eq $cur} { + # The current branch is older. + # + set reflog_msg "merge $new_expr: Fast-forward" + } else { + switch -- $merge_type { + ff { + if {$merge_base eq $new} { + # The current branch is actually newer. + # + set new $cur + set new_hash $cur + } else { + _error $this [mc "Branch '%s' already exists.\n\nIt cannot fast-forward to %s.\nA merge is required." $newbranch $new_expr] + return 0 + } + } + reset { + # The current branch will lose things. + # + if {[_confirm_reset $this $cur]} { + set reflog_msg "reset $new_expr" + } else { + return 0 + } + } + default { + _error $this [mc "Merge strategy '%s' not supported." $merge_type] + return 0 + } + } + } + } + + if {$new ne $cur} { + if {$is_current} { + # No so fast. We should defer this in case + # we cannot update the working directory. + # + set update_old $cur + return 1 + } + + if {[catch { + git update-ref -m $reflog_msg $ref $new $cur + } err]} { + _error $this [strcat [mc "Failed to update '%s'." $newbranch] "\n\n$err"] + return 0 + } + } + + return 1 +} + +method _checkout {} { + if {[lock_index checkout_op]} { + after idle [cb _start_checkout] + } else { + _error $this [mc "Staging area (index) is already locked."] + delete_this + } +} + +method _start_checkout {} { + global HEAD commit_type + + # -- Our in memory state should match the repository. + # + repository_state curType curHEAD curMERGE_HEAD + if {[string match amend* $commit_type] + && $curType eq {normal} + && $curHEAD eq $HEAD} { + } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} { + info_popup [mc "Last scanned state does not match repository state. + +Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed. + +The rescan will be automatically started now. +"] + unlock_index + rescan ui_ready + delete_this + return + } + + if {$curHEAD eq $new_hash} { + _after_readtree $this + } elseif {[is_config_true gui.trustmtime]} { + _readtree $this + } else { - ui_status {Refreshing file status...} ++ ui_status [mc "Refreshing file status..."] + set fd [git_read update-index \ + -q \ + --unmerged \ + --ignore-missing \ + --refresh \ + ] + fconfigure $fd -blocking 0 -translation binary + fileevent $fd readable [cb _refresh_wait $fd] + } +} + +method _refresh_wait {fd} { + read $fd + if {[eof $fd]} { + close $fd + _readtree $this + } +} + +method _name {} { + if {$new_ref eq {}} { + return [string range $new_hash 0 7] + } + + set rh refs/heads/ + set rn [string length $rh] + if {[string equal -length $rn $rh $new_ref]} { + return [string range $new_ref $rn end] + } else { + return $new_ref + } +} + +method _readtree {} { + global HEAD + + set readtree_d {} + $::main_status start \ + [mc "Updating working directory to '%s'..." [_name $this]] \ - {files checked out} ++ [mc "files checked out"] + + set fd [git_read --stderr read-tree \ + -m \ + -u \ + -v \ + --exclude-per-directory=.gitignore \ + $HEAD \ + $new_hash \ + ] + fconfigure $fd -blocking 0 -translation binary + fileevent $fd readable [cb _readtree_wait $fd] +} + +method _readtree_wait {fd} { + global current_branch + + set buf [read $fd] + $::main_status update_meter $buf + append readtree_d $buf + + fconfigure $fd -blocking 1 + if {![eof $fd]} { + fconfigure $fd -blocking 0 + return + } + + if {[catch {close $fd}]} { + set err $readtree_d + regsub {^fatal: } $err {} err + $::main_status stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]] + warn_popup [strcat [mc "File level merge required."] " + +$err + +" [mc "Staying on branch '%s'." $current_branch]] + unlock_index + delete_this + return + } + + $::main_status stop + _after_readtree $this +} + +method _after_readtree {} { + global selected_commit_type commit_type HEAD MERGE_HEAD PARENT + global current_branch is_detached + global ui_comm + + set name [_name $this] + set log "checkout: moving" + if {!$is_detached} { + append log " from $current_branch" + } + + # -- Move/create HEAD as a symbolic ref. Core git does not + # even check for failure 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. + # + set rh refs/heads/ + set rn [string length $rh] + if {[string equal -length $rn $rh $new_ref]} { + set new_branch [string range $new_ref $rn end] + if {$is_detached || $current_branch ne $new_branch} { + append log " to $new_branch" + if {[catch { + git symbolic-ref -m $log HEAD $new_ref + } err]} { + _fatal $this $err + } + set current_branch $new_branch + set is_detached 0 + } + } else { + if {!$is_detached || $new_hash ne $HEAD} { + append log " to $new_expr" + if {[catch { + _detach_HEAD $log $new_hash + } err]} { + _fatal $this $err + } + } + set current_branch HEAD + set is_detached 1 + } + + # -- We had to defer updating the branch itself until we + # knew the working directory would update. So now we + # need to finish that work. If it fails we're in big + # trouble. + # + if {$update_old ne {}} { + if {[catch { + git update-ref \ + -m $reflog_msg \ + $new_ref \ + $new_hash \ + $update_old + } err]} { + _fatal $this $err + } + } + + if {$is_detached} { + info_popup [mc "You are no longer on a local branch. + +If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."] + } + + # -- Update our repository state. If we were previously in + # amend mode we need to toss the current buffer and do a + # full rescan to update our file lists. If we weren't in + # amend mode our file lists are accurate and we can avoid + # the rescan. + # + unlock_index + set selected_commit_type new + if {[string match amend* $commit_type]} { + $ui_comm delete 0.0 end + $ui_comm edit reset + $ui_comm edit modified false + rescan [list ui_status [mc "Checked out '%s'." $name]] + } else { + repository_state commit_type HEAD MERGE_HEAD + set PARENT $HEAD - ui_status "Checked out '$name'." ++ ui_status [mc "Checked out '%s'." $name] + } + delete_this +} + +git-version proc _detach_HEAD {log new} { + >= 1.5.3 { + git update-ref --no-deref -m $log HEAD $new + } + default { + set p [gitdir HEAD] + file delete $p + set fd [open $p w] + fconfigure $fd -translation lf -encoding utf-8 + puts $fd $new + close $fd + } +} + +method _confirm_reset {cur} { + set reset_ok 0 + set name [_name $this] + set gitk [list do_gitk [list $cur ^$new_hash]] + + _toplevel $this {Confirm Branch Reset} + pack [label $w.msg1 \ + -anchor w \ + -justify left \ + -text [mc "Resetting '%s' to '%s' will lose the following commits:" $name $new_expr]\ + ] -anchor w + + set list $w.list.l + frame $w.list + text $list \ + -font font_diff \ + -width 80 \ + -height 10 \ + -wrap none \ + -xscrollcommand [list $w.list.sbx set] \ + -yscrollcommand [list $w.list.sby set] + scrollbar $w.list.sbx -orient h -command [list $list xview] + scrollbar $w.list.sby -orient v -command [list $list yview] + pack $w.list.sbx -fill x -side bottom + pack $w.list.sby -fill y -side right + pack $list -fill both -expand 1 + pack $w.list -fill both -expand 1 -padx 5 -pady 5 + + pack [label $w.msg2 \ + -anchor w \ + -justify left \ + -text [mc "Recovering lost commits may not be easy."] \ + ] + pack [label $w.msg3 \ + -anchor w \ + -justify left \ + -text [mc "Reset '%s'?" $name] \ + ] + + frame $w.buttons + button $w.buttons.visualize \ + -text [mc Visualize] \ + -command $gitk + pack $w.buttons.visualize -side left + button $w.buttons.reset \ + -text [mc Reset] \ + -command " + set @reset_ok 1 + destroy $w + " + pack $w.buttons.reset -side right + button $w.buttons.cancel \ + -default active \ + -text [mc Cancel] \ + -command [list destroy $w] + pack $w.buttons.cancel -side right -padx 5 + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + set fd [git_read rev-list --pretty=oneline $cur ^$new_hash] + while {[gets $fd line] > 0} { + set abbr [string range $line 0 7] + set subj [string range $line 41 end] + $list insert end "$abbr $subj\n" + } + close $fd + $list configure -state disabled + + bind $w $gitk + bind $w " + grab $w + focus $w.buttons.cancel + " + bind $w [list destroy $w] + bind $w [list destroy $w] + tkwait window $w + return $reset_ok +} + +method _error {msg} { + if {[winfo ismapped $parent_w]} { + set p $parent_w + } else { + set p . + } + + tk_messageBox \ + -icon error \ + -type ok \ + -title [wm title $p] \ + -parent $p \ + -message $msg +} + +method _toplevel {title} { + regsub -all {::} $this {__} w + set w .$w + + if {[winfo ismapped $parent_w]} { + set p $parent_w + } else { + set p . + } + + toplevel $w + wm title $w $title + wm geometry $w "+[winfo rootx $p]+[winfo rooty $p]" +} + +method _fatal {err} { + error_popup [strcat [mc "Failed to set current branch. + +This working directory is only partially switched. We successfully updated your files, but failed to update an internal Git file. + +This should not have occurred. %s will now close and give up." [appname]] " + +$err"] + exit 1 +} + +} diff --cc git-gui/lib/commit.tcl index 947b201c3,000000000..40a710355 mode 100644,000000..100644 --- a/git-gui/lib/commit.tcl +++ b/git-gui/lib/commit.tcl @@@ -1,470 -1,0 +1,470 @@@ +# git-gui misc. commit reading/writing support +# Copyright (C) 2006, 2007 Shawn Pearce + +proc load_last_commit {} { + global HEAD PARENT MERGE_HEAD commit_type ui_comm + global repo_config + + if {[llength $PARENT] == 0} { + error_popup [mc "There is nothing to amend. + +You are about to create the initial commit. There is no commit before this to amend. +"] + return + } + + repository_state curType curHEAD curMERGE_HEAD + if {$curType eq {merge}} { + error_popup [mc "Cannot amend while merging. + +You are currently in the middle of a merge that has not been fully completed. You cannot amend the prior commit unless you first abort the current merge activity. +"] + return + } + + set msg {} + set parents [list] + if {[catch { + set fd [git_read cat-file commit $curHEAD] + fconfigure $fd -encoding binary -translation lf + if {[catch {set enc $repo_config(i18n.commitencoding)}]} { + set enc utf-8 + } + while {[gets $fd line] > 0} { + if {[string match {parent *} $line]} { + lappend parents [string range $line 7 end] + } elseif {[string match {encoding *} $line]} { + set enc [string tolower [string range $line 9 end]] + } + } + set msg [read $fd] + close $fd + + set enc [tcl_encoding $enc] + if {$enc ne {}} { + set msg [encoding convertfrom $enc $msg] + } + set msg [string trim $msg] + } err]} { + error_popup [strcat [mc "Error loading commit data for amend:"] "\n\n$err"] + return + } + + set HEAD $curHEAD + set PARENT $parents + set MERGE_HEAD [list] + switch -- [llength $parents] { + 0 {set commit_type amend-initial} + 1 {set commit_type amend} + default {set commit_type amend-merge} + } + + $ui_comm delete 0.0 end + $ui_comm insert end $msg + $ui_comm edit reset + $ui_comm edit modified false + rescan ui_ready +} + +set GIT_COMMITTER_IDENT {} + +proc committer_ident {} { + global GIT_COMMITTER_IDENT + + if {$GIT_COMMITTER_IDENT eq {}} { + if {[catch {set me [git var GIT_COMMITTER_IDENT]} err]} { + error_popup [strcat [mc "Unable to obtain your identity:"] "\n\n$err"] + return {} + } + if {![regexp {^(.*) [0-9]+ [-+0-9]+$} \ + $me me GIT_COMMITTER_IDENT]} { + error_popup [strcat [mc "Invalid GIT_COMMITTER_IDENT:"] "\n\n$me"] + return {} + } + } + + return $GIT_COMMITTER_IDENT +} + +proc do_signoff {} { + global ui_comm + + set me [committer_ident] + if {$me eq {}} return + + set sob "Signed-off-by: $me" + set last [$ui_comm get {end -1c linestart} {end -1c}] + if {$last ne $sob} { + $ui_comm edit separator + if {$last ne {} + && ![regexp {^[A-Z][A-Za-z]*-[A-Za-z-]+: *} $last]} { + $ui_comm insert end "\n" + } + $ui_comm insert end "\n$sob" + $ui_comm edit separator + $ui_comm see end + } +} + +proc create_new_commit {} { + global commit_type ui_comm + + set commit_type normal + $ui_comm delete 0.0 end + $ui_comm edit reset + $ui_comm edit modified false + rescan ui_ready +} + +proc commit_tree {} { + global HEAD commit_type file_states ui_comm repo_config + global pch_error + + if {[committer_ident] eq {}} return + if {![lock_index update]} return + + # -- Our in memory state should match the repository. + # + repository_state curType curHEAD curMERGE_HEAD + if {[string match amend* $commit_type] + && $curType eq {normal} + && $curHEAD eq $HEAD} { + } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} { + info_popup [mc "Last scanned state does not match repository state. + +Another Git program has modified this repository since the last scan. A rescan must be performed before another commit can be created. + +The rescan will be automatically started now. +"] + unlock_index + rescan ui_ready + return + } + + # -- At least one file should differ in the index. + # + set files_ready 0 + foreach path [array names file_states] { + switch -glob -- [lindex $file_states($path) 0] { + _? {continue} + A? - + D? - + M? {set files_ready 1} + U? { + error_popup [mc "Unmerged files cannot be committed. + +File %s has merge conflicts. You must resolve them and stage the file before committing. +" [short_path $path]] + unlock_index + return + } + default { + error_popup [mc "Unknown file state %s detected. + +File %s cannot be committed by this program. +" [lindex $s 0] [short_path $path]] + } + } + } + if {!$files_ready && ![string match *merge $curType]} { + info_popup [mc "No changes to commit. + +You must stage at least 1 file before you can commit. +"] + unlock_index + return + } + + # -- A message is required. + # + set msg [string trim [$ui_comm get 1.0 end]] + regsub -all -line {[ \t\r]+$} $msg {} msg + if {$msg eq {}} { + error_popup [mc "Please supply a commit message. + +A good commit message has the following format: + +- First line: Describe in one sentence what you did. +- Second line: Blank +- Remaining lines: Describe why this change is good. +"] + unlock_index + return + } + + # -- Build the message file. + # + set msg_p [gitdir GITGUI_EDITMSG] + set msg_wt [open $msg_p w] + fconfigure $msg_wt -translation lf + if {[catch {set enc $repo_config(i18n.commitencoding)}]} { + set enc utf-8 + } + set use_enc [tcl_encoding $enc] + if {$use_enc ne {}} { + fconfigure $msg_wt -encoding $use_enc + } else { + puts stderr [mc "warning: Tcl does not support encoding '%s'." $enc] + fconfigure $msg_wt -encoding utf-8 + } + puts $msg_wt $msg + close $msg_wt + + # -- Run the pre-commit hook. + # + set fd_ph [githook_read pre-commit] + if {$fd_ph eq {}} { + commit_commitmsg $curHEAD $msg_p + return + } + - ui_status {Calling pre-commit hook...} ++ ui_status [mc "Calling pre-commit hook..."] + set pch_error {} + fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} + fileevent $fd_ph readable \ + [list commit_prehook_wait $fd_ph $curHEAD $msg_p] +} + +proc commit_prehook_wait {fd_ph curHEAD msg_p} { + global pch_error + + append pch_error [read $fd_ph] + fconfigure $fd_ph -blocking 1 + if {[eof $fd_ph]} { + if {[catch {close $fd_ph}]} { + catch {file delete $msg_p} - ui_status {Commit declined by pre-commit hook.} ++ ui_status [mc "Commit declined by pre-commit hook."] + hook_failed_popup pre-commit $pch_error + unlock_index + } else { + commit_commitmsg $curHEAD $msg_p + } + set pch_error {} + return + } + fconfigure $fd_ph -blocking 0 +} + +proc commit_commitmsg {curHEAD msg_p} { + global pch_error + + # -- Run the commit-msg hook. + # + set fd_ph [githook_read commit-msg $msg_p] + if {$fd_ph eq {}} { + commit_writetree $curHEAD $msg_p + return + } + - ui_status {Calling commit-msg hook...} ++ ui_status [mc "Calling commit-msg hook..."] + set pch_error {} + fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} + fileevent $fd_ph readable \ + [list commit_commitmsg_wait $fd_ph $curHEAD $msg_p] +} + +proc commit_commitmsg_wait {fd_ph curHEAD msg_p} { + global pch_error + + append pch_error [read $fd_ph] + fconfigure $fd_ph -blocking 1 + if {[eof $fd_ph]} { + if {[catch {close $fd_ph}]} { + catch {file delete $msg_p} - ui_status {Commit declined by commit-msg hook.} ++ ui_status [mc "Commit declined by commit-msg hook."] + hook_failed_popup commit-msg $pch_error + unlock_index + } else { + commit_writetree $curHEAD $msg_p + } + set pch_error {} + return + } + fconfigure $fd_ph -blocking 0 +} + +proc commit_writetree {curHEAD msg_p} { - ui_status {Committing changes...} ++ ui_status [mc "Committing changes..."] + set fd_wt [git_read write-tree] + fileevent $fd_wt readable \ + [list commit_committree $fd_wt $curHEAD $msg_p] +} + +proc commit_committree {fd_wt curHEAD msg_p} { + global HEAD PARENT MERGE_HEAD commit_type + global current_branch + global ui_comm selected_commit_type + global file_states selected_paths rescan_active + global repo_config + + gets $fd_wt tree_id + if {[catch {close $fd_wt} err]} { + catch {file delete $msg_p} + error_popup [strcat [mc "write-tree failed:"] "\n\n$err"] - ui_status {Commit failed.} ++ ui_status [mc "Commit failed."] + unlock_index + return + } + + # -- Verify this wasn't an empty change. + # + if {$commit_type eq {normal}} { + set fd_ot [git_read cat-file commit $PARENT] + fconfigure $fd_ot -encoding binary -translation lf + set old_tree [gets $fd_ot] + close $fd_ot + + if {[string equal -length 5 {tree } $old_tree] + && [string length $old_tree] == 45} { + set old_tree [string range $old_tree 5 end] + } else { + error [mc "Commit %s appears to be corrupt" $PARENT] + } + + if {$tree_id eq $old_tree} { + catch {file delete $msg_p} + info_popup [mc "No changes to commit. + +No files were modified by this commit and it was not a merge commit. + +A rescan will be automatically started now. +"] + unlock_index + rescan {ui_status [mc "No changes to commit."]} + return + } + } + + # -- Create the commit. + # + set cmd [list commit-tree $tree_id] + foreach p [concat $PARENT $MERGE_HEAD] { + lappend cmd -p $p + } + lappend cmd <$msg_p + if {[catch {set cmt_id [eval git $cmd]} err]} { + catch {file delete $msg_p} + error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"] - ui_status {Commit failed.} ++ ui_status [mc "Commit failed."] + unlock_index + return + } + + # -- Update the HEAD ref. + # + set reflogm commit + if {$commit_type ne {normal}} { + append reflogm " ($commit_type)" + } + set msg_fd [open $msg_p r] + gets $msg_fd subject + close $msg_fd + append reflogm {: } $subject + if {[catch { + git update-ref -m $reflogm HEAD $cmt_id $curHEAD + } err]} { + catch {file delete $msg_p} + error_popup [strcat [mc "update-ref failed:"] "\n\n$err"] - ui_status {Commit failed.} ++ ui_status [mc "Commit failed."] + unlock_index + return + } + + # -- Cleanup after ourselves. + # + catch {file delete $msg_p} + catch {file delete [gitdir MERGE_HEAD]} + catch {file delete [gitdir MERGE_MSG]} + catch {file delete [gitdir SQUASH_MSG]} + catch {file delete [gitdir GITGUI_MSG]} + + # -- Let rerere do its thing. + # + if {[get_config rerere.enabled] eq {}} { + set rerere [file isdirectory [gitdir rr-cache]] + } else { + set rerere [is_config_true rerere.enabled] + } + if {$rerere} { + catch {git rerere} + } + + # -- Run the post-commit hook. + # + set fd_ph [githook_read post-commit] + if {$fd_ph ne {}} { + upvar #0 pch_error$cmt_id pc_err + set pc_err {} + fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} + fileevent $fd_ph readable \ + [list commit_postcommit_wait $fd_ph $cmt_id] + } + + $ui_comm delete 0.0 end + $ui_comm edit reset + $ui_comm edit modified false + if {$::GITGUI_BCK_exists} { + catch {file delete [gitdir GITGUI_BCK]} + set ::GITGUI_BCK_exists 0 + } + + if {[is_enabled singlecommit]} do_quit + + # -- Update in memory status + # + set selected_commit_type new + set commit_type normal + set HEAD $cmt_id + set PARENT $cmt_id + set MERGE_HEAD [list] + + foreach path [array names file_states] { + set s $file_states($path) + set m [lindex $s 0] + switch -glob -- $m { + _O - + _M - + _D {continue} + __ - + A_ - + M_ - + D_ { + unset file_states($path) + catch {unset selected_paths($path)} + } + DO { + set file_states($path) [list _O [lindex $s 1] {} {}] + } + AM - + AD - + MM - + MD { + set file_states($path) [list \ + _[string index $m 1] \ + [lindex $s 1] \ + [lindex $s 3] \ + {}] + } + } + } + + display_all_files + unlock_index + reshow_diff + ui_status [mc "Created commit %s: %s" [string range $cmt_id 0 7] $subject] +} + +proc commit_postcommit_wait {fd_ph cmt_id} { + upvar #0 pch_error$cmt_id pch_error + + append pch_error [read $fd_ph] + fconfigure $fd_ph -blocking 1 + if {[eof $fd_ph]} { + if {[catch {close $fd_ph}]} { + hook_failed_popup post-commit $pch_error 0 + } + unset pch_error + return + } + fconfigure $fd_ph -blocking 0 +} diff --cc git-gui/lib/index.tcl index 30a244cc1,000000000..3c1fce747 mode 100644,000000..100644 --- a/git-gui/lib/index.tcl +++ b/git-gui/lib/index.tcl @@@ -1,437 -1,0 +1,437 @@@ +# git-gui index (add/remove) support +# Copyright (C) 2006, 2007 Shawn Pearce + +proc _delete_indexlock {} { + if {[catch {file delete -- [gitdir index.lock]} err]} { + error_popup [strcat [mc "Unable to unlock the index."] "\n\n$err"] + } +} + +proc _close_updateindex {fd after} { + fconfigure $fd -blocking 1 + if {[catch {close $fd} err]} { + set w .indexfried + toplevel $w + wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]] + wm geometry $w "+[winfo rootx .]+[winfo rooty .]" + pack [label $w.msg \ + -justify left \ + -anchor w \ + -text [strcat \ + [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."] \ + "\n\n$err"] \ + ] -anchor w + + frame $w.buttons + button $w.buttons.continue \ + -text [mc "Continue"] \ + -command [list destroy $w] + pack $w.buttons.continue -side right -padx 5 + button $w.buttons.unlock \ + -text [mc "Unlock Index"] \ + -command "destroy $w; _delete_indexlock" + pack $w.buttons.unlock -side right + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + wm protocol $w WM_DELETE_WINDOW update + bind $w.buttons.continue " + grab $w + focus $w.buttons.continue + " + tkwait window $w + + $::main_status stop + unlock_index + rescan $after 0 + return + } + + $::main_status stop + unlock_index + uplevel #0 $after +} + +proc update_indexinfo {msg pathList after} { + global update_index_cp + + if {![lock_index update]} return + + set update_index_cp 0 + set pathList [lsort $pathList] + set totalCnt [llength $pathList] + set batch [expr {int($totalCnt * .01) + 1}] + if {$batch > 25} {set batch 25} + + $::main_status start $msg [mc "files"] + set fd [git_write update-index -z --index-info] + fconfigure $fd \ + -blocking 0 \ + -buffering full \ + -buffersize 512 \ + -encoding binary \ + -translation binary + fileevent $fd writable [list \ + write_update_indexinfo \ + $fd \ + $pathList \ + $totalCnt \ + $batch \ + $after \ + ] +} + +proc write_update_indexinfo {fd pathList totalCnt batch after} { + global update_index_cp + global file_states current_diff_path + + if {$update_index_cp >= $totalCnt} { + _close_updateindex $fd $after + return + } + + for {set i $batch} \ + {$update_index_cp < $totalCnt && $i > 0} \ + {incr i -1} { + set path [lindex $pathList $update_index_cp] + incr update_index_cp + + set s $file_states($path) + switch -glob -- [lindex $s 0] { + A? {set new _O} + M? {set new _M} + D_ {set new _D} + D? {set new _?} + ?? {continue} + } + set info [lindex $s 2] + if {$info eq {}} continue + + puts -nonewline $fd "$info\t[encoding convertto $path]\0" + display_file $path $new + } + + $::main_status update $update_index_cp $totalCnt +} + +proc update_index {msg pathList after} { + global update_index_cp + + if {![lock_index update]} return + + set update_index_cp 0 + set pathList [lsort $pathList] + set totalCnt [llength $pathList] + set batch [expr {int($totalCnt * .01) + 1}] + if {$batch > 25} {set batch 25} + + $::main_status start $msg [mc "files"] + set fd [git_write update-index --add --remove -z --stdin] + fconfigure $fd \ + -blocking 0 \ + -buffering full \ + -buffersize 512 \ + -encoding binary \ + -translation binary + fileevent $fd writable [list \ + write_update_index \ + $fd \ + $pathList \ + $totalCnt \ + $batch \ + $after \ + ] +} + +proc write_update_index {fd pathList totalCnt batch after} { + global update_index_cp + global file_states current_diff_path + + if {$update_index_cp >= $totalCnt} { + _close_updateindex $fd $after + return + } + + for {set i $batch} \ + {$update_index_cp < $totalCnt && $i > 0} \ + {incr i -1} { + set path [lindex $pathList $update_index_cp] + incr update_index_cp + + switch -glob -- [lindex $file_states($path) 0] { + AD {set new __} + ?D {set new D_} + _O - + AM {set new A_} + U? { + if {[file exists $path]} { + set new M_ + } else { + set new D_ + } + } + ?M {set new M_} + ?? {continue} + } + puts -nonewline $fd "[encoding convertto $path]\0" + display_file $path $new + } + + $::main_status update $update_index_cp $totalCnt +} + +proc checkout_index {msg pathList after} { + global update_index_cp + + if {![lock_index update]} return + + set update_index_cp 0 + set pathList [lsort $pathList] + set totalCnt [llength $pathList] + set batch [expr {int($totalCnt * .01) + 1}] + if {$batch > 25} {set batch 25} + + $::main_status start $msg [mc "files"] + set fd [git_write checkout-index \ + --index \ + --quiet \ + --force \ + -z \ + --stdin \ + ] + fconfigure $fd \ + -blocking 0 \ + -buffering full \ + -buffersize 512 \ + -encoding binary \ + -translation binary + fileevent $fd writable [list \ + write_checkout_index \ + $fd \ + $pathList \ + $totalCnt \ + $batch \ + $after \ + ] +} + +proc write_checkout_index {fd pathList totalCnt batch after} { + global update_index_cp + global file_states current_diff_path + + if {$update_index_cp >= $totalCnt} { + _close_updateindex $fd $after + return + } + + for {set i $batch} \ + {$update_index_cp < $totalCnt && $i > 0} \ + {incr i -1} { + set path [lindex $pathList $update_index_cp] + incr update_index_cp + switch -glob -- [lindex $file_states($path) 0] { + U? {continue} + ?M - + ?D { + puts -nonewline $fd "[encoding convertto $path]\0" + display_file $path ?_ + } + } + } + + $::main_status update $update_index_cp $totalCnt +} + +proc unstage_helper {txt paths} { + global file_states current_diff_path + + if {![lock_index begin-update]} return + + set pathList [list] + set after {} + foreach path $paths { + switch -glob -- [lindex $file_states($path) 0] { + A? - + M? - + D? { + lappend pathList $path + if {$path eq $current_diff_path} { + set after {reshow_diff;} + } + } + } + } + if {$pathList eq {}} { + unlock_index + } else { + update_indexinfo \ + $txt \ + $pathList \ + [concat $after [list ui_ready]] + } +} + +proc do_unstage_selection {} { + global current_diff_path selected_paths + + if {[array size selected_paths] > 0} { + unstage_helper \ + {Unstaging selected files from commit} \ + [array names selected_paths] + } elseif {$current_diff_path ne {}} { + unstage_helper \ + [mc "Unstaging %s from commit" [short_path $current_diff_path]] \ + [list $current_diff_path] + } +} + +proc add_helper {txt paths} { + global file_states current_diff_path + + if {![lock_index begin-update]} return + + set pathList [list] + set after {} + foreach path $paths { + switch -glob -- [lindex $file_states($path) 0] { + _O - + ?M - + ?D - + U? { + lappend pathList $path + if {$path eq $current_diff_path} { + set after {reshow_diff;} + } + } + } + } + if {$pathList eq {}} { + unlock_index + } else { + update_index \ + $txt \ + $pathList \ - [concat $after {ui_status {Ready to commit.}}] ++ [concat $after {ui_status [mc "Ready to commit."]}] + } +} + +proc do_add_selection {} { + global current_diff_path selected_paths + + if {[array size selected_paths] > 0} { + add_helper \ + {Adding selected files} \ + [array names selected_paths] + } elseif {$current_diff_path ne {}} { + add_helper \ + [mc "Adding %s" [short_path $current_diff_path]] \ + [list $current_diff_path] + } +} + +proc do_add_all {} { + global file_states + + set paths [list] + foreach path [array names file_states] { + switch -glob -- [lindex $file_states($path) 0] { + U? {continue} + ?M - + ?D {lappend paths $path} + } + } + add_helper {Adding all changed files} $paths +} + +proc revert_helper {txt paths} { + global file_states current_diff_path + + if {![lock_index begin-update]} return + + set pathList [list] + set after {} + foreach path $paths { + switch -glob -- [lindex $file_states($path) 0] { + U? {continue} + ?M - + ?D { + lappend pathList $path + if {$path eq $current_diff_path} { + set after {reshow_diff;} + } + } + } + } + + + # Split question between singular and plural cases, because + # such distinction is needed in some languages. Previously, the + # code used "Revert changes in" for both, but that can't work + # in languages where 'in' must be combined with word from + # rest of string (in diffrent way for both cases of course). + # + # FIXME: Unfortunately, even that isn't enough in some languages + # as they have quite complex plural-form rules. Unfortunately, + # msgcat doesn't seem to support that kind of string translation. + # + set n [llength $pathList] + if {$n == 0} { + unlock_index + return + } elseif {$n == 1} { + set query [mc "Revert changes in file %s?" [short_path [lindex $pathList]]] + } else { + set query [mc "Revert changes in these %i files?" $n] + } + + set reply [tk_dialog \ + .confirm_revert \ + "[appname] ([reponame])" \ + "$query + +[mc "Any unstaged changes will be permanently lost by the revert."]" \ + question \ + 1 \ + [mc "Do Nothing"] \ + [mc "Revert Changes"] \ + ] + if {$reply == 1} { + checkout_index \ + $txt \ + $pathList \ + [concat $after [list ui_ready]] + } else { + unlock_index + } +} + +proc do_revert_selection {} { + global current_diff_path selected_paths + + if {[array size selected_paths] > 0} { + revert_helper \ + {Reverting selected files} \ + [array names selected_paths] + } elseif {$current_diff_path ne {}} { + revert_helper \ + "Reverting [short_path $current_diff_path]" \ + [list $current_diff_path] + } +} + +proc do_select_commit_type {} { + global commit_type selected_commit_type + + if {$selected_commit_type eq {new} + && [string match amend* $commit_type]} { + create_new_commit + } elseif {$selected_commit_type eq {amend} + && ![string match amend* $commit_type]} { + load_last_commit + + # The amend request was rejected... + # + if {![string match amend* $commit_type]} { + set selected_commit_type new + } + } +} diff --cc git-gui/lib/merge.tcl index 63e14279c,000000000..cc26b0780 mode 100644,000000..100644 --- a/git-gui/lib/merge.tcl +++ b/git-gui/lib/merge.tcl @@@ -1,274 -1,0 +1,273 @@@ +# git-gui branch merge support +# Copyright (C) 2006, 2007 Shawn Pearce + +class merge { + +field w ; # top level window +field w_rev ; # mega-widget to pick the revision to merge + +method _can_merge {} { + global HEAD commit_type file_states + + if {[string match amend* $commit_type]} { + info_popup [mc "Cannot merge while amending. + +You must finish amending this commit before starting any type of merge. +"] + return 0 + } + + if {[committer_ident] eq {}} {return 0} + if {![lock_index merge]} {return 0} + + # -- Our in memory state should match the repository. + # + repository_state curType curHEAD curMERGE_HEAD + if {$commit_type ne $curType || $HEAD ne $curHEAD} { + info_popup [mc "Last scanned state does not match repository state. + +Another Git program has modified this repository since the last scan. A rescan must be performed before a merge can be performed. + +The rescan will be automatically started now. +"] + unlock_index + rescan ui_ready + return 0 + } + + foreach path [array names file_states] { + switch -glob -- [lindex $file_states($path) 0] { + _O { + continue; # and pray it works! + } + U? { + error_popup [mc "You are in the middle of a conflicted merge. + +File %s has merge conflicts. + +You must resolve them, stage the file, and commit to complete the current merge. Only then can you begin another merge. +" [short_path $path]] + unlock_index + return 0 + } + ?? { + error_popup [mc "You are in the middle of a change. + +File %s is modified. + +You should complete the current commit before starting a merge. Doing so will help you abort a failed merge, should the need arise. +" [short_path $path]] + unlock_index + return 0 + } + } + } + + return 1 +} + +method _rev {} { + if {[catch {$w_rev commit_or_die}]} { + return {} + } + return [$w_rev get] +} + +method _visualize {} { + set rev [_rev $this] + if {$rev ne {}} { + do_gitk [list $rev --not HEAD] + } +} + +method _start {} { + global HEAD current_branch remote_url + + set name [_rev $this] + if {$name eq {}} { + return + } + + set spec [$w_rev get_tracking_branch] + set cmit [$w_rev get_commit] + + set fh [open [gitdir FETCH_HEAD] w] + fconfigure $fh -translation lf + if {$spec eq {}} { + set remote . + set branch $name + set stitle $branch + } else { + set remote $remote_url([lindex $spec 1]) + if {[regexp {^[^:@]*@[^:]*:/} $remote]} { + regsub {^[^:@]*@} $remote {} remote + } + set branch [lindex $spec 2] + set stitle [mc "%s of %s" $branch $remote] + } + regsub ^refs/heads/ $branch {} branch + puts $fh "$cmit\t\tbranch '$branch' of $remote" + close $fh + + set cmd [list git] + lappend cmd merge + lappend cmd --strategy=recursive + lappend cmd [git fmt-merge-msg <[gitdir FETCH_HEAD]] + lappend cmd HEAD + lappend cmd $name + - set msg [mc "Merging %s and %s" $current_branch $stitle] - ui_status "$msg..." ++ ui_status [mc "Merging %s and %s..." $current_branch $stitle] + set cons [console::new [mc "Merge"] "merge $stitle"] + console::exec $cons $cmd [cb _finish $cons] + + wm protocol $w WM_DELETE_WINDOW {} + destroy $w +} + +method _finish {cons ok} { + console::done $cons $ok + if {$ok} { + set msg [mc "Merge completed successfully."] + } else { + set msg [mc "Merge failed. Conflict resolution is required."] + } + unlock_index + rescan [list ui_status $msg] + delete_this +} + +constructor dialog {} { + global current_branch + global M1B + + if {![_can_merge $this]} { + delete_this + return + } + + make_toplevel top w + wm title $top [append "[appname] ([reponame]): " [mc "Merge"]] + if {$top ne {.}} { + wm geometry $top "+[winfo rootx .]+[winfo rooty .]" + } + + set _start [cb _start] + + label $w.header \ + -text [mc "Merge Into %s" $current_branch] \ + -font font_uibold + pack $w.header -side top -fill x + + frame $w.buttons + button $w.buttons.visualize \ + -text [mc Visualize] \ + -command [cb _visualize] + pack $w.buttons.visualize -side left + button $w.buttons.merge \ + -text [mc Merge] \ + -command $_start + pack $w.buttons.merge -side right + button $w.buttons.cancel \ + -text [mc "Cancel"] \ + -command [cb _cancel] + pack $w.buttons.cancel -side right -padx 5 + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + set w_rev [::choose_rev::new_unmerged $w.rev [mc "Revision To Merge"]] + pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 + + bind $w <$M1B-Key-Return> $_start + bind $w $_start + bind $w [cb _cancel] + wm protocol $w WM_DELETE_WINDOW [cb _cancel] + + bind $w.buttons.merge [cb _visible] + tkwait window $w +} + +method _visible {} { + grab $w + if {[is_config_true gui.matchtrackingbranch]} { + $w_rev pick_tracking_branch + } + $w_rev focus_filter +} + +method _cancel {} { + wm protocol $w WM_DELETE_WINDOW {} + unlock_index + destroy $w + delete_this +} + +} + +namespace eval merge { + +proc reset_hard {} { + global HEAD commit_type file_states + + if {[string match amend* $commit_type]} { + info_popup [mc "Cannot abort while amending. + +You must finish amending this commit. +"] + return + } + + if {![lock_index abort]} return + + if {[string match *merge* $commit_type]} { + set op_question [mc "Abort merge? + +Aborting the current merge will cause *ALL* uncommitted changes to be lost. + +Continue with aborting the current merge?"] + } else { + set op_question [mc "Reset changes? + +Resetting the changes will cause *ALL* uncommitted changes to be lost. + +Continue with resetting the current changes?"] + } + + if {[ask_popup $op_question] eq {yes}} { + set fd [git_read --stderr read-tree --reset -u -v HEAD] + fconfigure $fd -blocking 0 -translation binary + fileevent $fd readable [namespace code [list _reset_wait $fd]] - $::main_status start [mc "Aborting"] {files reset} ++ $::main_status start [mc "Aborting"] [mc "files reset"] + } else { + unlock_index + } +} + +proc _reset_wait {fd} { + global ui_comm + + $::main_status update_meter [read $fd] + + fconfigure $fd -blocking 1 + if {[eof $fd]} { + set fail [catch {close $fd} err] + $::main_status stop + unlock_index + + $ui_comm delete 0.0 end + $ui_comm edit modified false + + catch {file delete [gitdir MERGE_HEAD]} + catch {file delete [gitdir rr-cache MERGE_RR]} + catch {file delete [gitdir SQUASH_MSG]} + catch {file delete [gitdir MERGE_MSG]} + catch {file delete [gitdir GITGUI_MSG]} + + if {$fail} { + warn_popup "[mc "Abort failed."]\n\n$err" + } + rescan {ui_status [mc "Abort completed. Ready."]} + } else { + fconfigure $fd -blocking 0 + } +} + +} diff --cc git-gui/lib/option.tcl index f812e5e89,000000000..3bfa2edf1 mode 100644,000000..100644 --- a/git-gui/lib/option.tcl +++ b/git-gui/lib/option.tcl @@@ -1,239 -1,0 +1,280 @@@ +# git-gui options editor +# Copyright (C) 2006, 2007 Shawn Pearce + +proc save_config {} { + global default_config font_descs + global repo_config global_config + global repo_config_new global_config_new ++ global ui_comm_spell + + foreach option $font_descs { + set name [lindex $option 0] + set font [lindex $option 1] + font configure $font \ + -family $global_config_new(gui.$font^^family) \ + -size $global_config_new(gui.$font^^size) + font configure ${font}bold \ + -family $global_config_new(gui.$font^^family) \ + -size $global_config_new(gui.$font^^size) + font configure ${font}italic \ + -family $global_config_new(gui.$font^^family) \ + -size $global_config_new(gui.$font^^size) + set global_config_new(gui.$name) [font configure $font] + unset global_config_new(gui.$font^^family) + unset global_config_new(gui.$font^^size) + } + + foreach name [array names default_config] { + set value $global_config_new($name) + if {$value ne $global_config($name)} { + if {$value eq $default_config($name)} { + catch {git config --global --unset $name} + } else { + regsub -all "\[{}\]" $value {"} value + git config --global $name $value + } + set global_config($name) $value + if {$value eq $repo_config($name)} { + catch {git config --unset $name} + set repo_config($name) $value + } + } + } + + foreach name [array names default_config] { + set value $repo_config_new($name) + if {$value ne $repo_config($name)} { + if {$value eq $global_config($name)} { + catch {git config --unset $name} + } else { + regsub -all "\[{}\]" $value {"} value + git config $name $value + } + set repo_config($name) $value + } + } ++ ++ if {[info exists repo_config(gui.spellingdictionary)]} { ++ set value $repo_config(gui.spellingdictionary) ++ if {$value eq {none}} { ++ if {[info exists ui_comm_spell]} { ++ $ui_comm_spell stop ++ } ++ } elseif {[info exists ui_comm_spell]} { ++ $ui_comm_spell lang $value ++ } ++ } +} + +proc do_options {} { + global repo_config global_config font_descs + global repo_config_new global_config_new ++ global ui_comm_spell + + array unset repo_config_new + array unset global_config_new + foreach name [array names repo_config] { + set repo_config_new($name) $repo_config($name) + } + load_config 1 + foreach name [array names repo_config] { + switch -- $name { + gui.diffcontext {continue} + } + set repo_config_new($name) $repo_config($name) + } + foreach name [array names global_config] { + set global_config_new($name) $global_config($name) + } + + set w .options_editor + toplevel $w + wm geometry $w "+[winfo rootx .]+[winfo rooty .]" + + frame $w.buttons + button $w.buttons.restore -text [mc "Restore Defaults"] \ + -default normal \ + -command do_restore_defaults + pack $w.buttons.restore -side left + button $w.buttons.save -text [mc Save] \ + -default active \ + -command [list do_save_config $w] + pack $w.buttons.save -side right + button $w.buttons.cancel -text [mc "Cancel"] \ + -default normal \ + -command [list destroy $w] + pack $w.buttons.cancel -side right -padx 5 + pack $w.buttons -side bottom -fill x -pady 10 -padx 10 + + labelframe $w.repo -text [mc "%s Repository" [reponame]] + labelframe $w.global -text [mc "Global (All Repositories)"] + pack $w.repo -side left -fill both -expand 1 -pady 5 -padx 5 + pack $w.global -side right -fill both -expand 1 -pady 5 -padx 5 + + set optid 0 + foreach option { + {t user.name {mc "User Name"}} + {t user.email {mc "Email Address"}} + + {b merge.summary {mc "Summarize Merge Commits"}} + {i-1..5 merge.verbosity {mc "Merge Verbosity"}} + {b merge.diffstat {mc "Show Diffstat After Merge"}} + + {b gui.trustmtime {mc "Trust File Modification Timestamps"}} + {b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}} + {b gui.matchtrackingbranch {mc "Match Tracking Branches"}} + {i-0..99 gui.diffcontext {mc "Number of Diff Context Lines"}} + {t gui.newbranchtemplate {mc "New Branch Name Template"}} + } { + set type [lindex $option 0] + set name [lindex $option 1] + set text [eval [lindex $option 2]] + incr optid + foreach f {repo global} { + switch -glob -- $type { + b { + checkbutton $w.$f.$optid -text $text \ + -variable ${f}_config_new($name) \ + -onvalue true \ + -offvalue false + pack $w.$f.$optid -side top -anchor w + } + i-* { + regexp -- {-(\d+)\.\.(\d+)$} $type _junk min max + frame $w.$f.$optid + label $w.$f.$optid.l -text "$text:" + pack $w.$f.$optid.l -side left -anchor w -fill x + spinbox $w.$f.$optid.v \ + -textvariable ${f}_config_new($name) \ + -from $min \ + -to $max \ + -increment 1 \ + -width [expr {1 + [string length $max]}] + bind $w.$f.$optid.v {%W selection range 0 end} + pack $w.$f.$optid.v -side right -anchor e -padx 5 + pack $w.$f.$optid -side top -anchor w -fill x + } + t { + frame $w.$f.$optid + label $w.$f.$optid.l -text "$text:" + entry $w.$f.$optid.v \ + -borderwidth 1 \ + -relief sunken \ + -width 20 \ + -textvariable ${f}_config_new($name) + pack $w.$f.$optid.l -side left -anchor w + pack $w.$f.$optid.v -side left -anchor w \ + -fill x -expand 1 \ + -padx 5 + pack $w.$f.$optid -side top -anchor w -fill x + } + } + } + } + ++ set all_dicts [linsert \ ++ [spellcheck::available_langs] \ ++ 0 \ ++ none] ++ incr optid ++ foreach f {repo global} { ++ if {![info exists ${f}_config_new(gui.spellingdictionary)]} { ++ if {[info exists ui_comm_spell]} { ++ set value [$ui_comm_spell lang] ++ } else { ++ set value none ++ } ++ set ${f}_config_new(gui.spellingdictionary) $value ++ } ++ ++ frame $w.$f.$optid ++ label $w.$f.$optid.l -text [mc "Spelling Dictionary:"] ++ eval tk_optionMenu $w.$f.$optid.v \ ++ ${f}_config_new(gui.spellingdictionary) \ ++ $all_dicts ++ pack $w.$f.$optid.l -side left -anchor w -fill x ++ pack $w.$f.$optid.v -side left -anchor w \ ++ -fill x -expand 1 \ ++ -padx 5 ++ pack $w.$f.$optid -side top -anchor w -fill x ++ } ++ unset all_dicts ++ + set all_fonts [lsort [font families]] + foreach option $font_descs { + set name [lindex $option 0] + set font [lindex $option 1] + set text [eval [lindex $option 2]] + + set global_config_new(gui.$font^^family) \ + [font configure $font -family] + set global_config_new(gui.$font^^size) \ + [font configure $font -size] + + frame $w.global.$name + label $w.global.$name.l -text "$text:" + 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 + } + + bind $w "grab $w; focus $w.buttons.save" + bind $w "destroy $w" + bind $w [list do_save_config $w] + + if {[is_MacOSX]} { + set t [mc "Preferences"] + } else { + set t [mc "Options"] + } + wm title $w "[appname] ([reponame]): $t" + tkwait window $w +} + +proc do_restore_defaults {} { + global font_descs default_config repo_config + global repo_config_new global_config_new + + foreach name [array names default_config] { + set repo_config_new($name) $default_config($name) + set global_config_new($name) $default_config($name) + } + + foreach option $font_descs { + set name [lindex $option 0] + set repo_config(gui.$name) $default_config(gui.$name) + } + apply_config + + foreach option $font_descs { + set name [lindex $option 0] + set font [lindex $option 1] + set global_config_new(gui.$font^^family) \ + [font configure $font -family] + set global_config_new(gui.$font^^size) \ + [font configure $font -size] + } +} + +proc do_save_config {w} { + if {[catch {save_config} err]} { + error_popup [strcat [mc "Failed to completely save options:"] "\n\n$err"] + } + reshow_diff + destroy $w +} diff --cc git-gui/lib/spellcheck.tcl index 000000000,000000000..01c2c4f0d new file mode 100644 --- /dev/null +++ b/git-gui/lib/spellcheck.tcl @@@ -1,0 -1,0 +1,363 @@@ ++# git-gui spellchecking support through aspell ++# Copyright (C) 2008 Shawn Pearce ++ ++class spellcheck { ++ ++field s_fd {} ; # pipe to aspell ++field s_version ; # aspell version string ++field s_lang ; # current language code ++ ++field w_text ; # text widget we are spelling ++field w_menu ; # context menu for the widget ++field s_menuidx 0 ; # last index of insertion into $w_menu ++ ++field s_i ; # timer registration for _run callbacks ++field s_clear 0 ; # did we erase mispelled tags yet? ++field s_seen [list] ; # lines last seen from $w_text in _run ++field s_checked [list] ; # lines already checked ++field s_pending [list] ; # [$line $data] sent to aspell ++field s_suggest ; # array, list of suggestions, keyed by misspelling ++ ++constructor init {pipe_fd ui_text ui_menu} { ++ set w_text $ui_text ++ set w_menu $ui_menu ++ ++ _connect $this $pipe_fd ++ return $this ++} ++ ++method _connect {pipe_fd} { ++ fconfigure $pipe_fd \ ++ -encoding utf-8 \ ++ -eofchar {} \ ++ -translation lf ++ ++ if {[gets $pipe_fd s_version] <= 0} { ++ close $pipe_fd ++ error [mc "Not connected to aspell"] ++ } ++ if {{@(#) } ne [string range $s_version 0 4]} { ++ close $pipe_fd ++ error [strcat [mc "Unrecognized aspell version"] ": $s_version"] ++ } ++ set s_version [string range $s_version 5 end] ++ ++ puts $pipe_fd ! ; # enable terse mode ++ puts $pipe_fd {$$cr master} ; # fetch the language ++ flush $pipe_fd ++ ++ gets $pipe_fd s_lang ++ regexp {[/\\]([^/\\]+)\.[^\.]+$} $s_lang _ s_lang ++ ++ if {$::default_config(gui.spellingdictionary) eq {} ++ && [get_config gui.spellingdictionary] eq {}} { ++ set ::default_config(gui.spellingdictionary) $s_lang ++ } ++ ++ if {$s_fd ne {}} { ++ catch {close $s_fd} ++ } ++ set s_fd $pipe_fd ++ ++ fconfigure $s_fd -blocking 0 ++ fileevent $s_fd readable [cb _read] ++ ++ $w_text tag conf misspelled \ ++ -foreground red \ ++ -underline 1 ++ bind_button3 $w_text [cb _popup_suggest %X %Y @%x,%y] ++ ++ array unset s_suggest ++ set s_seen [list] ++ set s_checked [list] ++ set s_pending [list] ++ _run $this ++} ++ ++method lang {{n {}}} { ++ if {$n ne {} && $s_lang ne $n} { ++ set spell_cmd [list |] ++ lappend spell_cmd aspell ++ lappend spell_cmd --master=$n ++ lappend spell_cmd --mode=none ++ lappend spell_cmd --encoding=UTF-8 ++ lappend spell_cmd pipe ++ _connect $this [open $spell_cmd r+] ++ } ++ return $s_lang ++} ++ ++method version {} { ++ return "$s_version, $s_lang" ++} ++ ++method stop {} { ++ while {$s_menuidx > 0} { ++ $w_menu delete 0 ++ incr s_menuidx -1 ++ } ++ $w_text tag delete misspelled ++ ++ catch {close $s_fd} ++ catch {after cancel $s_i} ++ set s_fd {} ++ set s_i {} ++ set s_lang {} ++} ++ ++method _popup_suggest {X Y pos} { ++ while {$s_menuidx > 0} { ++ $w_menu delete 0 ++ incr s_menuidx -1 ++ } ++ ++ set b_loc [$w_text index "$pos wordstart"] ++ set e_loc [_wordend $this $b_loc] ++ set orig [$w_text get $b_loc $e_loc] ++ set tags [$w_text tag names $b_loc] ++ ++ if {[lsearch -exact $tags misspelled] >= 0} { ++ if {[info exists s_suggest($orig)]} { ++ set cnt 0 ++ foreach s $s_suggest($orig) { ++ if {$cnt < 5} { ++ $w_menu insert $s_menuidx command \ ++ -label $s \ ++ -command [cb _replace $b_loc $e_loc $s] ++ incr s_menuidx ++ incr cnt ++ } else { ++ break ++ } ++ } ++ } else { ++ $w_menu insert $s_menuidx command \ ++ -label [mc "No Suggestions"] \ ++ -state disabled ++ incr s_menuidx ++ } ++ $w_menu insert $s_menuidx separator ++ incr s_menuidx ++ } ++ ++ $w_text mark set saved-insert insert ++ tk_popup $w_menu $X $Y ++} ++ ++method _replace {b_loc e_loc word} { ++ $w_text configure -autoseparators 0 ++ $w_text edit separator ++ ++ $w_text delete $b_loc $e_loc ++ $w_text insert $b_loc $word ++ ++ $w_text edit separator ++ $w_text configure -autoseparators 1 ++ $w_text mark set insert saved-insert ++} ++ ++method _restart_timer {} { ++ set s_i [after 300 [cb _run]] ++} ++ ++proc _match_length {max_line arr_name} { ++ upvar $arr_name a ++ ++ if {[llength $a] > $max_line} { ++ set a [lrange $a 0 $max_line] ++ } ++ while {[llength $a] <= $max_line} { ++ lappend a {} ++ } ++} ++ ++method _wordend {pos} { ++ set pos [$w_text index "$pos wordend"] ++ set tags [$w_text tag names $pos] ++ while {[lsearch -exact $tags misspelled] >= 0} { ++ set pos [$w_text index "$pos +1c"] ++ set tags [$w_text tag names $pos] ++ } ++ return $pos ++} ++ ++method _run {} { ++ set cur_pos [$w_text index {insert -1c}] ++ set cur_line [lindex [split $cur_pos .] 0] ++ set max_line [lindex [split [$w_text index end] .] 0] ++ _match_length $max_line s_seen ++ _match_length $max_line s_checked ++ ++ # Nothing in the message buffer? Nothing to spellcheck. ++ # ++ if {$cur_line == 1 ++ && $max_line == 2 ++ && [$w_text get 1.0 end] eq "\n"} { ++ array unset s_suggest ++ _restart_timer $this ++ return ++ } ++ ++ set active 0 ++ for {set n 1} {$n <= $max_line} {incr n} { ++ set s [$w_text get "$n.0" "$n.end"] ++ ++ # Don't spellcheck the current line unless we are at ++ # a word boundary. The user might be typing on it. ++ # ++ if {$n == $cur_line ++ && ![regexp {^\W$} [$w_text get $cur_pos insert]]} { ++ ++ # If the current word is mispelled remove the tag ++ # but force a spellcheck later. ++ # ++ set tags [$w_text tag names $cur_pos] ++ if {[lsearch -exact $tags misspelled] >= 0} { ++ $w_text tag remove misspelled \ ++ "$cur_pos wordstart" \ ++ [_wordend $this $cur_pos] ++ lset s_seen $n $s ++ lset s_checked $n {} ++ } ++ ++ continue ++ } ++ ++ if {[lindex $s_seen $n] eq $s ++ && [lindex $s_checked $n] ne $s} { ++ # Don't send empty lines to Aspell it doesn't check them. ++ # ++ if {$s eq {}} { ++ lset s_checked $n $s ++ continue ++ } ++ ++ # Don't send typical s-b-o lines as the emails are ++ # almost always misspelled according to Aspell. ++ # ++ if {[regexp -nocase {^[a-z-]+-by:.*<.*@.*>$} $s]} { ++ $w_text tag remove misspelled "$n.0" "$n.end" ++ lset s_checked $n $s ++ continue ++ } ++ ++ puts $s_fd ^$s ++ lappend s_pending [list $n $s] ++ set active 1 ++ } else { ++ # Delay until another idle loop to make sure we don't ++ # spellcheck lines the user is actively changing. ++ # ++ lset s_seen $n $s ++ } ++ } ++ ++ if {$active} { ++ set s_clear 1 ++ flush $s_fd ++ } else { ++ _restart_timer $this ++ } ++} ++ ++method _read {} { ++ while {[gets $s_fd line] >= 0} { ++ set lineno [lindex $s_pending 0 0] ++ ++ if {$s_clear} { ++ $w_text tag remove misspelled "$lineno.0" "$lineno.end" ++ set s_clear 0 ++ } ++ ++ if {$line eq {}} { ++ lset s_checked $lineno [lindex $s_pending 0 1] ++ set s_pending [lrange $s_pending 1 end] ++ set s_clear 1 ++ continue ++ } ++ ++ set sugg [list] ++ switch -- [string range $line 0 1] { ++ {& } { ++ set line [split [string range $line 2 end] :] ++ set info [split [lindex $line 0] { }] ++ set orig [lindex $info 0] ++ set offs [lindex $info 2] ++ foreach s [split [lindex $line 1] ,] { ++ lappend sugg [string range $s 1 end] ++ } ++ } ++ {# } { ++ set info [split [string range $line 2 end] { }] ++ set orig [lindex $info 0] ++ set offs [lindex $info 1] ++ } ++ default { ++ puts stderr " $line" ++ continue ++ } ++ } ++ ++ incr offs -1 ++ set b_loc "$lineno.$offs" ++ set e_loc [$w_text index "$lineno.$offs wordend"] ++ set curr [$w_text get $b_loc $e_loc] ++ ++ # At least for English curr = "bob", orig = "bob's" ++ # so Tk didn't include the 's but Aspell did. We ++ # try to round out the word. ++ # ++ while {$curr ne $orig ++ && [string equal -length [llength $curr] $curr $orig]} { ++ set n_loc [$w_text index "$e_loc +1c"] ++ set n_curr [$w_text get $b_loc $n_loc] ++ if {$n_curr eq $curr} { ++ break ++ } ++ set curr $n_curr ++ set e_loc $n_loc ++ } ++ ++ if {$curr eq $orig} { ++ $w_text tag add misspelled $b_loc $e_loc ++ if {[llength $sugg] > 0} { ++ set s_suggest($orig) $sugg ++ } else { ++ unset -nocomplain s_suggest($orig) ++ } ++ } else { ++ unset -nocomplain s_suggest($orig) ++ } ++ } ++ ++ fconfigure $s_fd -block 1 ++ if {[eof $s_fd]} { ++ if {![catch {close $s_fd} err]} { ++ set err [mc "unexpected eof from aspell"] ++ } ++ catch {after cancel $s_i} ++ $w_text tag remove misspelled 1.0 end ++ error_popup [strcat "Spell Checker Failed" "\n\n" $err] ++ return ++ } ++ fconfigure $s_fd -block 0 ++ ++ if {[llength $s_pending] == 0} { ++ _restart_timer $this ++ } ++} ++ ++proc available_langs {} { ++ set langs [list] ++ catch { ++ set fd [open [list | aspell dump dicts] r] ++ while {[gets $fd line] >= 0} { ++ if {$line eq {}} continue ++ lappend langs $line ++ } ++ close $fd ++ } ++ return $langs ++} ++ ++} diff --cc git-gui/macosx/Info.plist index 99913ec57,000000000..b3bf15fa1 mode 100644,000000..100644 --- a/git-gui/macosx/Info.plist +++ b/git-gui/macosx/Info.plist @@@ -1,28 -1,0 +1,28 @@@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable - Wish ++ @@GITGUI_TKEXECUTABLE@@ + CFBundleGetInfoString + Git Gui @@GITGUI_VERSION@@ © 2006-2007 Shawn Pearce, et. al. + CFBundleIconFile + git-gui.icns + CFBundleIdentifier + cz.or.repo.git-gui + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Git Gui + CFBundlePackageType + APPL + CFBundleShortVersionString + @@GITGUI_VERSION@@ + CFBundleSignature + GITg + CFBundleVersion + @@GITGUI_VERSION@@ + + diff --cc git-gui/po/de.po index 2dfe07e06,000000000..d7c38f9c7 mode 100644,000000..100644 --- a/git-gui/po/de.po +++ b/git-gui/po/de.po @@@ -1,1903 -1,0 +1,1952 @@@ +# Translation of git-gui to German. +# Copyright (C) 2007 Shawn Pearce, et al. +# This file is distributed under the same license as the git package. +# Christian Stimming , 2007 +# +msgid "" +msgstr "" +"Project-Id-Version: git-gui\n" +"Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2007-11-24 10:36+0100\n" - "PO-Revision-Date: 2008-01-15 20:33+0100\n" ++"POT-Creation-Date: 2008-02-02 10:14+0100\n" ++"PO-Revision-Date: 2008-02-02 10:18+0100\n" +"Last-Translator: Christian Stimming \n" +"Language-Team: German\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: git-gui.sh:41 git-gui.sh:604 git-gui.sh:618 git-gui.sh:631 git-gui.sh:714 +#: git-gui.sh:733 +msgid "git-gui: fatal error" +msgstr "git-gui: Programmfehler" + +#: git-gui.sh:565 +#, tcl-format +msgid "Invalid font specified in %s:" +msgstr "Ungültige Zeichensatz-Angabe in %s:" + +#: git-gui.sh:590 +msgid "Main Font" +msgstr "Programmschriftart" + +#: git-gui.sh:591 +msgid "Diff/Console Font" +msgstr "Vergleich-Schriftart" + +#: git-gui.sh:605 +msgid "Cannot find git in PATH." +msgstr "Git kann im PATH nicht gefunden werden." + +#: git-gui.sh:632 +msgid "Cannot parse Git version string:" +msgstr "Git Versionsangabe kann nicht erkannt werden:" + +#: git-gui.sh:650 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" +"Die Version von Git kann nicht bestimmt werden.\n" +"\n" +"»%s« behauptet, es sei Version »%s«.\n" +"\n" +"%s benötigt mindestens Git 1.5.0 oder höher.\n" +"\n" +"Soll angenommen werden, »%s« sei Version 1.5.0?\n" + +#: git-gui.sh:888 +msgid "Git directory not found:" +msgstr "Git-Verzeichnis nicht gefunden:" + +#: git-gui.sh:895 +msgid "Cannot move to top of working directory:" +msgstr "" +"Es konnte nicht in das oberste Verzeichnis der Arbeitskopie gewechselt " +"werden:" + +#: git-gui.sh:902 +msgid "Cannot use funny .git directory:" +msgstr "Unerwartete Struktur des .git Verzeichnis:" + +#: git-gui.sh:907 +msgid "No working directory" +msgstr "Kein Arbeitsverzeichnis" + +#: git-gui.sh:1054 +msgid "Refreshing file status..." +msgstr "Dateistatus aktualisieren..." + +#: git-gui.sh:1119 +msgid "Scanning for modified files ..." +msgstr "Nach geänderten Dateien suchen..." + +#: git-gui.sh:1294 lib/browser.tcl:245 +msgid "Ready." +msgstr "Bereit." + +#: git-gui.sh:1560 +msgid "Unmodified" +msgstr "Unverändert" + +#: git-gui.sh:1562 +msgid "Modified, not staged" +msgstr "Verändert, nicht bereitgestellt" + +#: git-gui.sh:1563 git-gui.sh:1568 +msgid "Staged for commit" +msgstr "Bereitgestellt zum Eintragen" + +#: git-gui.sh:1564 git-gui.sh:1569 +msgid "Portions staged for commit" +msgstr "Teilweise bereitgestellt zum Eintragen" + +#: git-gui.sh:1565 git-gui.sh:1570 +msgid "Staged for commit, missing" +msgstr "Bereitgestellt zum Eintragen, fehlend" + +#: git-gui.sh:1567 +msgid "Untracked, not staged" +msgstr "Nicht unter Versionskontrolle, nicht bereitgestellt" + +#: git-gui.sh:1572 +msgid "Missing" +msgstr "Fehlend" + +#: git-gui.sh:1573 +msgid "Staged for removal" +msgstr "Bereitgestellt zum Löschen" + +#: git-gui.sh:1574 +msgid "Staged for removal, still present" +msgstr "Bereitgestellt zum Löschen, trotzdem vorhanden" + +#: git-gui.sh:1576 git-gui.sh:1577 git-gui.sh:1578 git-gui.sh:1579 +msgid "Requires merge resolution" +msgstr "Konfliktauflösung nötig" + +#: git-gui.sh:1614 +msgid "Starting gitk... please wait..." +msgstr "Gitk wird gestartet... bitte warten." + +#: git-gui.sh:1623 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" +"Gitk kann nicht gestartet werden:\n" +"\n" +"%s existiert nicht" + +#: git-gui.sh:1823 lib/choose_repository.tcl:35 +msgid "Repository" +msgstr "Projektarchiv" + +#: git-gui.sh:1824 +msgid "Edit" +msgstr "Bearbeiten" + +#: git-gui.sh:1826 lib/choose_rev.tcl:560 +msgid "Branch" +msgstr "Zweig" + +#: git-gui.sh:1829 lib/choose_rev.tcl:547 +msgid "Commit@@noun" +msgstr "Version" + +#: git-gui.sh:1832 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +msgid "Merge" +msgstr "Zusammenführen" + +#: git-gui.sh:1833 lib/choose_rev.tcl:556 +msgid "Remote" +msgstr "Andere Archive" + +#: git-gui.sh:1842 +msgid "Browse Current Branch's Files" +msgstr "Aktuellen Zweig durchblättern" + +#: git-gui.sh:1846 +msgid "Browse Branch Files..." +msgstr "Einen Zweig durchblättern..." + +#: git-gui.sh:1851 +msgid "Visualize Current Branch's History" +msgstr "Aktuellen Zweig darstellen" + +#: git-gui.sh:1855 +msgid "Visualize All Branch History" +msgstr "Alle Zweige darstellen" + +#: git-gui.sh:1862 +#, tcl-format +msgid "Browse %s's Files" +msgstr "Zweig »%s« durchblättern" + +#: git-gui.sh:1864 +#, tcl-format +msgid "Visualize %s's History" +msgstr "Historie von »%s« darstellen" + +#: git-gui.sh:1869 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "Datenbankstatistik" + +#: git-gui.sh:1872 lib/database.tcl:34 +msgid "Compress Database" +msgstr "Datenbank komprimieren" + +#: git-gui.sh:1875 +msgid "Verify Database" +msgstr "Datenbank überprüfen" + +#: git-gui.sh:1882 git-gui.sh:1886 git-gui.sh:1890 lib/shortcut.tcl:7 +#: lib/shortcut.tcl:39 lib/shortcut.tcl:71 +msgid "Create Desktop Icon" +msgstr "Desktop-Icon erstellen" + +#: git-gui.sh:1895 lib/choose_repository.tcl:176 lib/choose_repository.tcl:184 +msgid "Quit" +msgstr "Beenden" + +#: git-gui.sh:1902 +msgid "Undo" +msgstr "Rückgängig" + +#: git-gui.sh:1905 +msgid "Redo" +msgstr "Wiederholen" + +#: git-gui.sh:1909 git-gui.sh:2403 +msgid "Cut" +msgstr "Ausschneiden" + +#: git-gui.sh:1912 git-gui.sh:2406 git-gui.sh:2477 git-gui.sh:2549 +#: lib/console.tcl:67 +msgid "Copy" +msgstr "Kopieren" + +#: git-gui.sh:1915 git-gui.sh:2409 +msgid "Paste" +msgstr "Einfügen" + +#: git-gui.sh:1918 git-gui.sh:2412 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "Löschen" + +#: git-gui.sh:1922 git-gui.sh:2416 git-gui.sh:2553 lib/console.tcl:69 +msgid "Select All" +msgstr "Alle auswählen" + +#: git-gui.sh:1931 +msgid "Create..." +msgstr "Erstellen..." + +#: git-gui.sh:1937 +msgid "Checkout..." +msgstr "Umstellen..." + +#: git-gui.sh:1943 +msgid "Rename..." +msgstr "Umbenennen..." + +#: git-gui.sh:1948 git-gui.sh:2048 +msgid "Delete..." +msgstr "Löschen..." + +#: git-gui.sh:1953 +msgid "Reset..." +msgstr "Zurücksetzen..." + +#: git-gui.sh:1965 git-gui.sh:2350 +msgid "New Commit" +msgstr "Neue Version" + +#: git-gui.sh:1973 git-gui.sh:2357 +msgid "Amend Last Commit" +msgstr "Letzte nachbessern" + +#: git-gui.sh:1982 git-gui.sh:2317 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "Neu laden" + +#: git-gui.sh:1988 +msgid "Stage To Commit" +msgstr "Zum Eintragen bereitstellen" + +#: git-gui.sh:1994 +msgid "Stage Changed Files To Commit" +msgstr "Geänderte Dateien bereitstellen" + +#: git-gui.sh:2000 +msgid "Unstage From Commit" +msgstr "Aus der Bereitstellung herausnehmen" + +#: git-gui.sh:2005 lib/index.tcl:393 +msgid "Revert Changes" +msgstr "Änderungen verwerfen" + +#: git-gui.sh:2012 git-gui.sh:2329 git-gui.sh:2427 +msgid "Sign Off" +msgstr "Abzeichnen" + +#: git-gui.sh:2016 git-gui.sh:2333 +msgid "Commit@@verb" +msgstr "Eintragen" + +#: git-gui.sh:2027 +msgid "Local Merge..." +msgstr "Lokales Zusammenführen..." + +#: git-gui.sh:2032 +msgid "Abort Merge..." +msgstr "Zusammenführen abbrechen..." + +#: git-gui.sh:2044 +msgid "Push..." +msgstr "Versenden..." + +#: git-gui.sh:2055 lib/choose_repository.tcl:40 +msgid "Apple" +msgstr "Apple" + +#: git-gui.sh:2058 git-gui.sh:2080 lib/about.tcl:13 +#: lib/choose_repository.tcl:43 lib/choose_repository.tcl:49 +#, tcl-format +msgid "About %s" +msgstr "Über %s" + +#: git-gui.sh:2062 +msgid "Preferences..." +msgstr "Einstellungen..." + +#: git-gui.sh:2070 git-gui.sh:2595 +msgid "Options..." +msgstr "Optionen..." + +#: git-gui.sh:2076 lib/choose_repository.tcl:46 +msgid "Help" +msgstr "Hilfe" + +#: git-gui.sh:2117 +msgid "Online Documentation" +msgstr "Online-Dokumentation" + +#: git-gui.sh:2201 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" - msgstr "Fehler: Verzeichnis »%s« kann nicht gelesen werden: Datei oder Verzeichnis nicht gefunden" ++msgstr "" ++"Fehler: Verzeichnis »%s« kann nicht gelesen werden: Datei oder Verzeichnis " ++"nicht gefunden" + +#: git-gui.sh:2234 +msgid "Current Branch:" +msgstr "Aktueller Zweig:" + +#: git-gui.sh:2255 +msgid "Staged Changes (Will Commit)" +msgstr "Bereitstellung (zum Eintragen)" + +#: git-gui.sh:2274 +msgid "Unstaged Changes" +msgstr "Nicht bereitgestellte Änderungen" + +#: git-gui.sh:2323 +msgid "Stage Changed" +msgstr "Alles bereitstellen" + +#: git-gui.sh:2339 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "Versenden" + +#: git-gui.sh:2369 +msgid "Initial Commit Message:" +msgstr "Erste Versionsbeschreibung:" + +#: git-gui.sh:2370 +msgid "Amended Commit Message:" - msgstr "Nachgebesserte Versionsbeschreibung:" ++msgstr "Nachgebesserte Beschreibung:" + +#: git-gui.sh:2371 +msgid "Amended Initial Commit Message:" - msgstr "Nachgebesserte erste Versionsbeschreibung:" ++msgstr "Nachgebesserte erste Beschreibung:" + +#: git-gui.sh:2372 +msgid "Amended Merge Commit Message:" - msgstr "Nachgebesserte Zusammenführungs-Versionsbeschreibung:" ++msgstr "Nachgebesserte Zusammenführungs-Beschreibung:" + +#: git-gui.sh:2373 +msgid "Merge Commit Message:" - msgstr "Zusammenführungs-Versionsbeschreibung:" ++msgstr "Zusammenführungs-Beschreibung:" + +#: git-gui.sh:2374 +msgid "Commit Message:" +msgstr "Versionsbeschreibung:" + +#: git-gui.sh:2419 git-gui.sh:2557 lib/console.tcl:71 +msgid "Copy All" +msgstr "Alle kopieren" + +#: git-gui.sh:2443 lib/blame.tcl:104 +msgid "File:" +msgstr "Datei:" + - #: git-gui.sh:2545 - msgid "Refresh" - msgstr "Aktualisieren" - - #: git-gui.sh:2566 ++#: git-gui.sh:2573 +msgid "Apply/Reverse Hunk" +msgstr "Kontext anwenden/umkehren" + - #: git-gui.sh:2572 - msgid "Decrease Font Size" - msgstr "Schriftgröße verkleinern" - - #: git-gui.sh:2576 - msgid "Increase Font Size" - msgstr "Schriftgröße vergrößern" - - #: git-gui.sh:2581 ++#: git-gui.sh:2579 +msgid "Show Less Context" +msgstr "Weniger Zeilen anzeigen" + - #: git-gui.sh:2588 ++#: git-gui.sh:2586 +msgid "Show More Context" +msgstr "Mehr Zeilen anzeigen" + - #: git-gui.sh:2602 ++#: git-gui.sh:2594 ++msgid "Refresh" ++msgstr "Aktualisieren" ++ ++#: git-gui.sh:2615 ++msgid "Decrease Font Size" ++msgstr "Schriftgröße verkleinern" ++ ++#: git-gui.sh:2619 ++msgid "Increase Font Size" ++msgstr "Schriftgröße vergrößern" ++ ++#: git-gui.sh:2630 +msgid "Unstage Hunk From Commit" +msgstr "Kontext aus Bereitstellung herausnehmen" + +#: git-gui.sh:2604 +msgid "Stage Hunk For Commit" +msgstr "Kontext zur Bereitstellung hinzufügen" + +#: git-gui.sh:2623 +msgid "Initializing..." +msgstr "Initialisieren..." + +#: git-gui.sh:2718 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" +"Möglicherweise gibt es Probleme mit manchen Umgebungsvariablen.\n" +"\n" +"Die folgenden Umgebungsvariablen können vermutlich nicht \n" +"von %s an Git weitergegeben werden:\n" +"\n" + +#: git-gui.sh:2748 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" +"\n" +"Dies ist ein bekanntes Problem der Tcl-Version, die\n" +"in Cygwin mitgeliefert wird." + +#: git-gui.sh:2753 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" +"\n" +"\n" +"Um den Namen »%s« zu ändern, sollten Sie die \n" +"gewünschten Werte für die Einstellung user.name und \n" +"user.email in Ihre Datei ~/.gitconfig einfügen.\n" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "git-gui - eine grafische Oberfläche für Git." + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "Datei-Browser" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "Version:" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "Version kopieren" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "%s lesen..." + +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "Annotierungen für Kopieren/Verschieben werden geladen..." + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "Zeilen annotiert" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "Annotierungen für ursprünglichen Ort werden geladen..." + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "Annotierung vollständig." + +#: lib/blame.tcl:731 +msgid "Loading annotation..." +msgstr "Annotierung laden..." + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "Autor:" + +#: lib/blame.tcl:791 +msgid "Committer:" +msgstr "Eintragender:" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "Ursprüngliche Datei:" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "Ursprünglich von:" + +#: lib/blame.tcl:916 +msgid "In File:" +msgstr "In Datei:" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "Kopiert oder verschoben durch:" + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" - msgstr "Zweig umstellen" ++msgstr "Auf Zweig umstellen" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "Umstellen" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 +msgid "Cancel" +msgstr "Abbrechen" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 +msgid "Revision" +msgstr "Version" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 +msgid "Options" +msgstr "Optionen" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "Übernahmezweig anfordern" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "Verbindung zu lokalem Zweig lösen" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "Zweig erstellen" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "Neuen Zweig erstellen" + +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:375 +msgid "Create" +msgstr "Erstellen" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "Zweigname" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "Name:" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "Passend zu Übernahmezweig-Name" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "Anfangsversion" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "Existierenden Zweig aktualisieren:" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "Nein" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "Nur Schnellzusammenführung" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 +msgid "Reset" +msgstr "Zurücksetzen" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "Arbeitskopie umstellen nach Erstellen" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "Bitte wählen Sie einen Übernahmezweig." + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "Übernahmezweig »%s« ist kein Zweig im anderen Projektarchiv." + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "Bitte geben Sie einen Zweignamen an." + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "»%s« ist kein zulässiger Zweigname." + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "Zweig löschen" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "Lokalen Zweig löschen" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "Lokale Zweige" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "Nur löschen, wenn darin zusammengeführt" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "Immer (ohne Zusammenführungstest)" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "Folgende Zweige sind noch nicht mit »%s« zusammengeführt:" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" +"Gelöschte Zweige können nur mit größerem Aufwand wiederhergestellt werden.\n" +"\n" +"Gewählte Zweige jetzt löschen?" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" +"Fehler beim Löschen der Zweige:\n" +"%s" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "Zweig umbenennen" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "Umbenennen" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "Zweig:" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "Neuer Name:" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "Bitte wählen Sie einen Zweig zum umbenennen." + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "Zweig »%s« existiert bereits." + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "Fehler beim Umbenennen von »%s«." + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "Starten..." + +#: lib/browser.tcl:26 +msgid "File Browser" +msgstr "Datei-Browser" + +#: lib/browser.tcl:125 lib/browser.tcl:142 +#, tcl-format +msgid "Loading %s..." +msgstr "%s laden..." + +#: lib/browser.tcl:186 +msgid "[Up To Parent]" +msgstr "[Nach oben]" + +#: lib/browser.tcl:266 lib/browser.tcl:272 +msgid "Browse Branch Files" +msgstr "Dateien des Zweigs durchblättern" + +#: lib/browser.tcl:277 lib/choose_repository.tcl:391 +#: lib/choose_repository.tcl:482 lib/choose_repository.tcl:492 +#: lib/choose_repository.tcl:989 +msgid "Browse" +msgstr "Blättern" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "Änderungen »%s« von »%s« anfordern" + +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "Fehler: »%s« kann nicht als Zweig oder Version erkannt werden" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 +msgid "Close" +msgstr "Schließen" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "Zweig »%s« existiert nicht." + +#: lib/checkout_op.tcl:206 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" +"Zweig »%s« existiert bereits.\n" +"\n" +"Zweig kann nicht mit »%s« schnellzusammengeführt werden. Reguläres " +"Zusammenführen ist notwendig." + +#: lib/checkout_op.tcl:220 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "Zusammenführungsmethode »%s« nicht unterstützt." + +#: lib/checkout_op.tcl:239 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "Aktualisieren von »%s« fehlgeschlagen." + +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." +msgstr "Bereitstellung (»index«) ist zur Bearbeitung gesperrt (»locked«)." + +#: lib/checkout_op.tcl:266 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" +"\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " +"geändert. Vor dem Wechseln des lokalen Zweigs muss neu geladen werden.\n" +"\n" +"Es wird gleich neu geladen.\n" + +#: lib/checkout_op.tcl:322 +#, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "Arbeitskopie umstellen auf »%s«..." + ++#: lib/checkout_op.tcl:323 ++msgid "files checked out" ++msgstr "Dateien aktualisiert" ++ +#: lib/checkout_op.tcl:353 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "" - "Zweig umstellen von »%s« abgebrochen (Zusammenführen der Dateien ist " ++"Auf Zweig »%s« umstellen abgebrochen (Zusammenführen der Dateien ist " +"notwendig)." + +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "Zusammenführen der Dateien ist notwendig." + +#: lib/checkout_op.tcl:358 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "Es wird auf Zweig »%s« verblieben." + +#: lib/checkout_op.tcl:429 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" +"Die Arbeitskopie ist nicht auf einem lokalen Zweig.\n" +"\n" +"Wenn Sie auf einem Zweig arbeiten möchten, erstellen Sie bitte jetzt einen " +"Zweig mit der Auswahl »Abgetrennte Arbeitskopie-Version«." + +#: lib/checkout_op.tcl:446 +#, tcl-format +msgid "Checked out '%s'." +msgstr "Umgestellt auf »%s«." + +#: lib/checkout_op.tcl:478 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "Zurücksetzen von »%s« nach »%s« wird folgende Versionen verwerfen:" + +#: lib/checkout_op.tcl:500 +msgid "Recovering lost commits may not be easy." +msgstr "" +"Verworfene Versionen können nur mit größerem Aufwand wiederhergestellt " +"werden." + +#: lib/checkout_op.tcl:505 +#, tcl-format +msgid "Reset '%s'?" +msgstr "»%s« zurücksetzen?" + +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 +msgid "Visualize" +msgstr "Darstellen" + +#: lib/checkout_op.tcl:578 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" +"Lokaler Zweig kann nicht gesetzt werden.\n" +"\n" +"Diese Arbeitskopie ist nur teilweise umgestellt. Die Dateien sind korrekt " +"aktualisiert, aber einige interne Git-Dateien konnten nicht geändert " +"werden.\n" +"\n" +"Dies ist ein interner Programmfehler von %s. Programm wird jetzt abgebrochen." + +#: lib/choose_font.tcl:39 +msgid "Select" +msgstr "Auswählen" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "Schriftfamilie" + +#: lib/choose_font.tcl:73 +msgid "Font Size" +msgstr "Schriftgröße" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "Schriftbeispiel" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" +"Dies ist ein Beispieltext.\n" +"Wenn Ihnen dieser Text gefällt, sollten Sie diese Schriftart wählen." + +#: lib/choose_repository.tcl:27 +msgid "Git Gui" +msgstr "Git Gui" + +#: lib/choose_repository.tcl:80 lib/choose_repository.tcl:380 +msgid "Create New Repository" +msgstr "Neues Projektarchiv" + +#: lib/choose_repository.tcl:86 +msgid "New..." +msgstr "Neu..." + +#: lib/choose_repository.tcl:93 lib/choose_repository.tcl:468 +msgid "Clone Existing Repository" +msgstr "Projektarchiv klonen" + +#: lib/choose_repository.tcl:99 +msgid "Clone..." +msgstr "Klonen..." + +#: lib/choose_repository.tcl:106 lib/choose_repository.tcl:978 +msgid "Open Existing Repository" +msgstr "Projektarchiv öffnen" + +#: lib/choose_repository.tcl:112 +msgid "Open..." +msgstr "Öffnen..." + +#: lib/choose_repository.tcl:125 +msgid "Recent Repositories" +msgstr "Zuletzt benutzte Projektarchive" + +#: lib/choose_repository.tcl:131 +msgid "Open Recent Repository:" +msgstr "Zuletzt benutztes Projektarchiv öffnen:" + +#: lib/choose_repository.tcl:294 +#, tcl-format +msgid "Location %s already exists." +msgstr "Projektarchiv »%s« existiert bereits." + +#: lib/choose_repository.tcl:300 lib/choose_repository.tcl:307 +#: lib/choose_repository.tcl:314 +#, tcl-format +msgid "Failed to create repository %s:" +msgstr "Projektarchiv »%s« konnte nicht erstellt werden:" + +#: lib/choose_repository.tcl:385 lib/choose_repository.tcl:486 +msgid "Directory:" +msgstr "Verzeichnis:" + +#: lib/choose_repository.tcl:415 lib/choose_repository.tcl:544 +#: lib/choose_repository.tcl:1013 +msgid "Git Repository" +msgstr "Git Projektarchiv" + +#: lib/choose_repository.tcl:430 lib/choose_repository.tcl:437 +#, tcl-format +msgid "Directory %s already exists." +msgstr "Verzeichnis »%s« existiert bereits." + +#: lib/choose_repository.tcl:442 +#, tcl-format +msgid "File %s already exists." +msgstr "Datei »%s« existiert bereits." + +#: lib/choose_repository.tcl:463 +msgid "Clone" +msgstr "Klonen" + +#: lib/choose_repository.tcl:476 +msgid "URL:" +msgstr "URL:" + +#: lib/choose_repository.tcl:496 +msgid "Clone Type:" +msgstr "Art des Klonens:" + +#: lib/choose_repository.tcl:502 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "Standard (schnell, teilweise redundant, Hardlinks)" + +#: lib/choose_repository.tcl:508 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "Alles kopieren (langsamer, volle Redundanz)" + +#: lib/choose_repository.tcl:514 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "Verknüpft (schnell, nicht empfohlen, kein Backup)" + +#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597 +#: lib/choose_repository.tcl:738 lib/choose_repository.tcl:808 +#: lib/choose_repository.tcl:1019 lib/choose_repository.tcl:1027 +#, tcl-format +msgid "Not a Git repository: %s" +msgstr "Kein Git-Projektarchiv in »%s« gefunden." + +#: lib/choose_repository.tcl:586 +msgid "Standard only available for local repository." +msgstr "Standard ist nur für lokale Projektarchive verfügbar." + +#: lib/choose_repository.tcl:590 +msgid "Shared only available for local repository." +msgstr "Verknüpft ist nur für lokale Projektarchive verfügbar." + +#: lib/choose_repository.tcl:617 +msgid "Failed to configure origin" +msgstr "Der Ursprungsort konnte nicht eingerichtet werden" + +#: lib/choose_repository.tcl:629 +msgid "Counting objects" +msgstr "Objekte werden gezählt" + +#: lib/choose_repository.tcl:630 +msgid "buckets" +msgstr "Buckets" + +#: lib/choose_repository.tcl:654 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "Kopien von Objekten/Info/Alternates konnten nicht erstellt werden: %s" + +#: lib/choose_repository.tcl:690 +#, tcl-format +msgid "Nothing to clone from %s." +msgstr "Von »%s« konnte nichts geklont werden." + +#: lib/choose_repository.tcl:692 lib/choose_repository.tcl:906 +#: lib/choose_repository.tcl:918 +msgid "The 'master' branch has not been initialized." +msgstr "Der »master«-Zweig wurde noch nicht initialisiert." + +#: lib/choose_repository.tcl:705 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "Hardlinks nicht verfügbar. Stattdessen wird kopiert." + +#: lib/choose_repository.tcl:717 +#, tcl-format +msgid "Cloning from %s" +msgstr "Kopieren von »%s«" + +#: lib/choose_repository.tcl:748 +msgid "Copying objects" +msgstr "Objektdatenbank kopieren" + +#: lib/choose_repository.tcl:749 +msgid "KiB" +msgstr "KB" + +#: lib/choose_repository.tcl:773 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "Objekt kann nicht kopiert werden: %s" + +#: lib/choose_repository.tcl:783 +msgid "Linking objects" +msgstr "Objekte verlinken" + +#: lib/choose_repository.tcl:784 +msgid "objects" +msgstr "Objekte" + +#: lib/choose_repository.tcl:792 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "Für Objekt konnte kein Hardlink erstellt werden: %s" + +#: lib/choose_repository.tcl:847 +msgid "Cannot fetch branches and objects. See console output for details." - msgstr "Zweige und Objekte konnten nicht angefordert werden. Kontrollieren Sie die Ausgaben auf der Konsole für weitere Angaben." ++msgstr "" ++"Zweige und Objekte konnten nicht angefordert werden. Kontrollieren Sie die " ++"Ausgaben auf der Konsole für weitere Angaben." + +#: lib/choose_repository.tcl:858 +msgid "Cannot fetch tags. See console output for details." - msgstr "Markierungen konnten nicht angefordert werden. Kontrollieren Sie die Ausgaben auf der Konsole für weitere Angaben." ++msgstr "" ++"Markierungen konnten nicht angefordert werden. Kontrollieren Sie die " ++"Ausgaben auf der Konsole für weitere Angaben." + +#: lib/choose_repository.tcl:882 +msgid "Cannot determine HEAD. See console output for details." - msgstr "Die Zweigspitze (HEAD) konnte nicht gefunden werden. Kontrollieren Sie die Ausgaben auf der Konsole für weitere Angaben." ++msgstr "" ++"Die Zweigspitze (HEAD) konnte nicht gefunden werden. Kontrollieren Sie die " ++"Ausgaben auf der Konsole für weitere Angaben." + +#: lib/choose_repository.tcl:891 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "Verzeichnis »%s« kann nicht aufgeräumt werden." + +#: lib/choose_repository.tcl:897 +msgid "Clone failed." +msgstr "Klonen fehlgeschlagen." + +#: lib/choose_repository.tcl:904 +msgid "No default branch obtained." +msgstr "Kein voreingestellter Zweig gefunden." + +#: lib/choose_repository.tcl:915 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "»%s« wurde nicht als Version gefunden." + +#: lib/choose_repository.tcl:927 +msgid "Creating working directory" +msgstr "Arbeitskopie erstellen" + +#: lib/choose_repository.tcl:928 lib/index.tcl:65 lib/index.tcl:127 +#: lib/index.tcl:193 +msgid "files" +msgstr "Dateien" + +#: lib/choose_repository.tcl:957 +msgid "Initial file checkout failed." +msgstr "Erstellen der Arbeitskopie fehlgeschlagen." + +#: lib/choose_repository.tcl:973 +msgid "Open" +msgstr "Öffnen" + +#: lib/choose_repository.tcl:983 +msgid "Repository:" +msgstr "Projektarchiv:" + +#: lib/choose_repository.tcl:1033 +#, tcl-format +msgid "Failed to open repository %s:" +msgstr "Projektarchiv »%s« konnte nicht geöffnet werden." + +#: lib/choose_rev.tcl:53 +msgid "This Detached Checkout" +msgstr "Abgetrennte Arbeitskopie-Version" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "Version Regexp-Ausdruck:" + +#: lib/choose_rev.tcl:74 +msgid "Local Branch" +msgstr "Lokaler Zweig" + +#: lib/choose_rev.tcl:79 +msgid "Tracking Branch" +msgstr "Übernahmezweig" + +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 +msgid "Tag" +msgstr "Markierung" + +#: lib/choose_rev.tcl:317 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "Ungültige Version: %s" + +#: lib/choose_rev.tcl:338 +msgid "No revision selected." +msgstr "Keine Version ausgewählt." + +#: lib/choose_rev.tcl:346 +msgid "Revision expression is empty." +msgstr "Versions-Ausdruck ist leer." + +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "Aktualisiert" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "URL" + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" +"Keine Version zur Nachbesserung vorhanden.\n" +"\n" +"Sie sind dabei, die erste Version zu übertragen. Es gibt keine existierende " +"Version, die Sie nachbessern könnten.\n" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" +"Nachbesserung währen Zusammenführung nicht möglich.\n" +"\n" +"Sie haben das Zusammenführen von Versionen angefangen, aber noch nicht " +"beendet. Sie können keine vorige Übertragung nachbessern, solange eine " +"unfertige Zusammenführung existiert. Dazu müssen Sie die Zusammenführung " +"beenden oder abbrechen.\n" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "Fehler beim Laden der Versionsdaten für Nachbessern:" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "Benutzername konnte nicht bestimmt werden:" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "Ungültiger Wert von GIT_COMMITTER_INDENT:" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" +"\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " +"geändert. Vor dem Eintragen einer neuen Version muss neu geladen werden.\n" +"\n" +"Es wird gleich neu geladen.\n" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" +"Nicht zusammengeführte Dateien können nicht eingetragen werden.\n" +"\n" +"Die Datei »%s« hat noch nicht aufgelöste Zusammenführungs-Konflikte. Sie " +"müssen diese Konflikte auflösen, bevor Sie eintragen können.\n" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" +"Unbekannter Dateizustand »%s«.\n" +"\n" +"Datei »%s« kann nicht eingetragen werden.\n" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" +"Keine Änderungen vorhanden, die eingetragen werden könnten.\n" +"\n" +"Sie müssen mindestens eine Datei bereitstellen, bevor Sie eintragen können.\n" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentence what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" +"Bitte geben Sie eine Versionsbeschreibung ein.\n" +"\n" +"Eine gute Versionsbeschreibung enthält folgende Abschnitte:\n" +"\n" +"- Erste Zeile: Eine Zusammenfassung, was man gemacht hat.\n" +"\n" +"- Zweite Zeile: Leerzeile\n" +"\n" +"- Rest: Eine ausführliche Beschreibung, warum diese Änderung hilfreich ist.\n" + - #: lib/commit.tcl:257 ++#: lib/commit.tcl:207 ++#, tcl-format ++msgid "warning: Tcl does not support encoding '%s'." ++msgstr "Warning: Tcl/Tk unterstützt die Zeichencodierung »%s« nicht." ++ ++#: lib/commit.tcl:221 ++msgid "Calling pre-commit hook..." ++msgstr "" ++ ++#: lib/commit.tcl:236 ++msgid "Commit declined by pre-commit hook." ++msgstr "" ++ ++#: lib/commit.tcl:259 ++msgid "Calling commit-msg hook..." ++msgstr "" ++ ++#: lib/commit.tcl:274 ++msgid "Commit declined by commit-msg hook." ++msgstr "" ++ ++#: lib/commit.tcl:287 ++msgid "Committing changes..." ++msgstr "Änderungen eintragen..." ++ ++#: lib/commit.tcl:303 +msgid "write-tree failed:" +msgstr "write-tree fehlgeschlagen:" + - #: lib/commit.tcl:275 ++#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368 ++msgid "Commit failed." ++msgstr "Eintragen fehlgeschlagen." ++ ++#: lib/commit.tcl:321 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "Version »%s« scheint beschädigt zu sein" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" +"Keine Änderungen einzutragen.\n" +"\n" +"Es gibt keine geänderte Datei bei dieser Version und es wurde auch nichts " +"zusammengeführt.\n" +"\n" +"Das Arbeitsverzeichnis wird daher jetzt neu geladen.\n" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "Keine Änderungen, die eingetragen werden können." + - #: lib/commit.tcl:303 - #, tcl-format - msgid "warning: Tcl does not support encoding '%s'." - msgstr "Warning: Tcl/Tk unterstützt die Zeichencodierung »%s« nicht." - - #: lib/commit.tcl:317 ++#: lib/commit.tcl:347 +msgid "commit-tree failed:" +msgstr "commit-tree fehlgeschlagen:" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "update-ref fehlgeschlagen:" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "Version %s übertragen: %s" + +#: lib/console.tcl:57 +msgid "Working... please wait..." +msgstr "Verarbeitung. Bitte warten..." + +#: lib/console.tcl:183 +msgid "Success" +msgstr "Erfolgreich" + +#: lib/console.tcl:196 +msgid "Error: Command Failed" +msgstr "Fehler: Kommando fehlgeschlagen" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "Anzahl unverknüpfter Objekte" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "Festplattenplatz von unverknüpften Objekten" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "Anzahl komprimierter Objekte" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "Anzahl Komprimierungseinheiten" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "Festplattenplatz von komprimierten Objekten" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "Komprimierte Objekte, die zum Entfernen vorgesehen sind" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "Dateien im Mülleimer" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "Objektdatenbank komprimieren" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "Die Objektdatenbank durch »fsck-objects« überprüfen lassen" + +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" +"Dieses Projektarchiv enthält ungefähr %i nicht verknüpfte Objekte.\n" +"\n" +"Für eine optimale Performance wird empfohlen, die Datenbank des " +"Projektarchivs zu komprimieren, sobald mehr als %i nicht verknüpfte Objekte " +"vorliegen.\n" +"\n" +"Soll die Datenbank jetzt komprimiert werden?" + +#: lib/date.tcl:25 +#, tcl-format +msgid "Invalid date from Git: %s" +msgstr "Ungültiges Datum von Git: %s" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" +"Keine Änderungen feststellbar.\n" +"\n" +"»%s« enthält keine Änderungen. Zwar wurde das Änderungsdatum dieser Datei " +"von einem anderen Programm modifiziert, aber der Inhalt der Datei ist " +"unverändert.\n" +"\n" +"Das Arbeitsverzeichnis wird jetzt neu geladen, um diese Änderung bei allen " +"Dateien zu prüfen." + +#: lib/diff.tcl:81 +#, tcl-format +msgid "Loading diff of %s..." +msgstr "Vergleich von »%s« laden..." + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "Datei »%s« kann nicht angezeigt werden" + +#: lib/diff.tcl:115 +msgid "Error loading file:" +msgstr "Fehler beim Laden der Datei:" + +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "Git-Projektarchiv (Unterprojekt)" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "* Binärdatei (Inhalt wird nicht angezeigt)" + +#: lib/diff.tcl:185 +msgid "Error loading diff:" +msgstr "Fehler beim Laden des Vergleichs:" + +#: lib/diff.tcl:302 +msgid "Failed to unstage selected hunk." - msgstr "Fehler beim Herausnehmen des gewählten Kontexts aus der Bereitstellung." ++msgstr "" ++"Fehler beim Herausnehmen des gewählten Kontexts aus der Bereitstellung." + +#: lib/diff.tcl:309 +msgid "Failed to stage selected hunk." +msgstr "Fehler beim Bereitstellen des gewählten Kontexts." + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "Fehler" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "Warnung" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "" +"Sie müssen die obigen Fehler zuerst beheben, bevor Sie eintragen können." + +#: lib/index.tcl:6 +msgid "Unable to unlock the index." +msgstr "Bereitstellung kann nicht wieder freigegeben werden." + +#: lib/index.tcl:15 +msgid "Index Error" +msgstr "Fehler in Bereitstellung" + +#: lib/index.tcl:21 +msgid "" +"Updating the Git index failed. A rescan will be automatically started to " +"resynchronize git-gui." - msgstr "Das Aktualisieren der Git-Bereitstellung ist fehlgeschlagen. Eine allgemeine Git-Aktualisierung wird jetzt gestartet, um git-gui wieder mit git zu synchronisieren." ++msgstr "" ++"Das Aktualisieren der Git-Bereitstellung ist fehlgeschlagen. Eine allgemeine " ++"Git-Aktualisierung wird jetzt gestartet, um git-gui wieder mit git zu " ++"synchronisieren." + +#: lib/index.tcl:27 +msgid "Continue" +msgstr "Fortsetzen" + +#: lib/index.tcl:31 +msgid "Unlock Index" +msgstr "Bereitstellung freigeben" + +#: lib/index.tcl:282 +#, tcl-format +msgid "Unstaging %s from commit" +msgstr "Datei »%s« aus der Bereitstellung herausnehmen" + ++#: lib/index.tcl:313 ++msgid "Ready to commit." ++msgstr "Bereit zum Eintragen." ++ +#: lib/index.tcl:326 +#, tcl-format +msgid "Adding %s" +msgstr "»%s« hinzufügen..." + +#: lib/index.tcl:381 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "Änderungen in Datei »%s« verwerfen?" + +#: lib/index.tcl:383 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "Änderungen in den gewählten %i Dateien verwerfen?" + +#: lib/index.tcl:389 +msgid "Any unstaged changes will be permanently lost by the revert." - msgstr "Alle nicht bereitgestellten Änderungen werden beim Verwerfen verloren gehen." ++msgstr "" ++"Alle nicht bereitgestellten Änderungen werden beim Verwerfen verloren gehen." + +#: lib/index.tcl:392 +msgid "Do Nothing" +msgstr "Nichts tun" + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" +"Zusammenführen kann nicht gleichzeitig mit Nachbessern durchgeführt werden.\n" +"\n" +"Sie müssen zuerst die Nachbesserungs-Version abschließen, bevor Sie " +"zusammenführen können.\n" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" +"Der letzte geladene Status stimmt nicht mehr mit dem Projektarchiv überein.\n" +"\n" +"Ein anderes Git-Programm hat das Projektarchiv seit dem letzten Laden " +"geändert. Vor einem Zusammenführen muss neu geladen werden.\n" +"\n" +"Es wird gleich neu geladen.\n" + +#: lib/merge.tcl:44 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" +"Zusammenführung mit Konflikten.\n" +"\n" +"Die Datei »%s« enthält Konflikte beim Zusammenführen. Sie müssen diese " +"Konflikte per Hand auflösen. Anschließend müssen Sie die Datei wieder " +"bereitstellen und eintragen, um die Zusammenführung abzuschließen. Erst " +"danach kann eine neue Zusammenführung begonnen werden.\n" + +#: lib/merge.tcl:54 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" +"Es liegen Änderungen vor.\n" +"\n" +"Die Datei »%s« wurde geändert. Sie sollten zuerst die bereitgestellte " +"Version abschließen, bevor Sie eine Zusammenführung beginnen. Mit dieser " +"Reihenfolge können Sie mögliche Konflikte beim Zusammenführen wesentlich " +"einfacher beheben oder abbrechen.\n" + +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "%s von %s" + +#: lib/merge.tcl:119 +#, tcl-format +msgid "Merging %s and %s" +msgstr "Zusammenführen von %s und %s" + +#: lib/merge.tcl:131 +msgid "Merge completed successfully." +msgstr "Zusammenführen erfolgreich abgeschlossen." + +#: lib/merge.tcl:133 +msgid "Merge failed. Conflict resolution is required." +msgstr "Zusammenführen fehlgeschlagen. Konfliktauflösung ist notwendig." + +#: lib/merge.tcl:158 +#, tcl-format +msgid "Merge Into %s" +msgstr "Zusammenführen in %s" + +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "Zusammenzuführende Version" + +#: lib/merge.tcl:212 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" +"Abbruch der Nachbesserung ist nicht möglich.\n" +"\n" +"Sie müssen die Nachbesserung der Version abschließen.\n" + +#: lib/merge.tcl:222 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" +"Zusammenführen abbrechen?\n" +"\n" +"Wenn Sie abbrechen, gehen alle noch nicht eingetragenen Änderungen " +"verloren.\n" +"\n" +"Zusammenführen jetzt abbrechen?" + +#: lib/merge.tcl:228 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" +"Änderungen zurücksetzen?\n" +"\n" +"Wenn Sie zurücksetzen, gehen alle noch nicht eingetragenen Änderungen " +"verloren.\n" +"\n" +"Änderungen jetzt zurücksetzen?" + +#: lib/merge.tcl:239 +msgid "Aborting" +msgstr "Abbruch" + - #: lib/merge.tcl:266 ++#: lib/merge.tcl:238 ++msgid "files reset" ++msgstr "Dateien zurückgesetzt" ++ ++#: lib/merge.tcl:265 +msgid "Abort failed." +msgstr "Abbruch fehlgeschlagen." + +#: lib/merge.tcl:268 +msgid "Abort completed. Ready." +msgstr "Abbruch durchgeführt. Bereit." + +#: lib/option.tcl:82 +msgid "Restore Defaults" +msgstr "Voreinstellungen wiederherstellen" + +#: lib/option.tcl:86 +msgid "Save" +msgstr "Speichern" + +#: lib/option.tcl:96 +#, tcl-format +msgid "%s Repository" +msgstr "Projektarchiv %s" + +#: lib/option.tcl:97 +msgid "Global (All Repositories)" +msgstr "Global (Alle Projektarchive)" + +#: lib/option.tcl:103 +msgid "User Name" +msgstr "Benutzername" + +#: lib/option.tcl:104 +msgid "Email Address" +msgstr "E-Mail-Adresse" + +#: lib/option.tcl:106 +msgid "Summarize Merge Commits" +msgstr "Zusammenführungs-Versionen zusammenfassen" + +#: lib/option.tcl:107 +msgid "Merge Verbosity" +msgstr "Ausführlichkeit der Zusammenführen-Meldungen" + +#: lib/option.tcl:108 +msgid "Show Diffstat After Merge" +msgstr "Vergleichsstatistik nach Zusammenführen anzeigen" + +#: lib/option.tcl:110 +msgid "Trust File Modification Timestamps" +msgstr "Auf Dateiänderungsdatum verlassen" + +#: lib/option.tcl:111 +msgid "Prune Tracking Branches During Fetch" +msgstr "Übernahmezweige entfernen während Anforderung" + +#: lib/option.tcl:112 +msgid "Match Tracking Branches" +msgstr "Passend zu Übernahmezweig" + +#: lib/option.tcl:113 +msgid "Number of Diff Context Lines" +msgstr "Anzahl der Kontextzeilen beim Vergleich" + +#: lib/option.tcl:114 +msgid "New Branch Name Template" +msgstr "Namensvorschlag für neue Zweige" + +#: lib/option.tcl:176 +msgid "Change Font" +msgstr "Schriftart ändern" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" +msgstr "%s wählen" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "pt." + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "Einstellungen" + +#: lib/option.tcl:235 +msgid "Failed to completely save options:" +msgstr "Optionen konnten nicht gespeichert werden:" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "Zweig aus anderem Projektarchiv löschen" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "Von Projektarchiv" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 +msgid "Remote:" +msgstr "Anderes Archiv:" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 +msgid "Arbitrary URL:" +msgstr "Kommunikation mit URL:" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "Zweige" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "Löschen, falls" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "Zusammenführen mit:" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "Immer (Keine Zusammenführungsprüfung)" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "Für »Zusammenführen mit« muss ein Zweig angegeben werden." + +#: lib/remote_branch_delete.tcl:184 +#, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "" +"Folgende Zweige sind noch nicht mit »%s« zusammengeführt:\n" +"\n" +" - %s" + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" +"Ein oder mehrere Zusammenführungen sind fehlgeschlagen, da Sie nicht die " +"notwendigen Versionen vorher angefordert haben. Sie sollten versuchen, " +"zuerst von »%s« anzufordern." + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "Bitte wählen Sie mindestens einen Zweig, der gelöscht werden soll." + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" +"Das Wiederherstellen von gelöschten Zweigen ist nur mit größerem Aufwand " +"möglich.\n" +"\n" +"Sollen die ausgewählten Zweige gelöscht werden?" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "Zweige auf »%s« werden gelöscht" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "Kein Projektarchiv ausgewählt." + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "»%s« laden..." + +#: lib/remote.tcl:165 +msgid "Prune from" +msgstr "Entfernen von" + +#: lib/remote.tcl:170 +msgid "Fetch from" +msgstr "Anfordern von" + +#: lib/remote.tcl:213 +msgid "Push to" +msgstr "Versenden nach" + +#: lib/shortcut.tcl:20 lib/shortcut.tcl:61 +msgid "Cannot write shortcut:" +msgstr "Fehler beim Schreiben der Verknüpfung:" + +#: lib/shortcut.tcl:136 +msgid "Cannot write icon:" +msgstr "Fehler beim Erstellen des Icons:" + +#: lib/status_bar.tcl:83 +#, tcl-format +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "%s ... %*i von %*i %s (%3i%%)" + +#: lib/transport.tcl:6 +#, tcl-format +msgid "fetch %s" +msgstr "»%s« anfordern" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "Neue Änderungen von »%s« holen" + +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "Entfernen von »%s« aus anderem Archiv" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "Übernahmezweige entfernen, die in »%s« gelöscht wurden" + +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "»%s« versenden..." + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "Änderungen nach »%s« versenden" + +#: lib/transport.tcl:72 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "%s %s nach %s versenden" + +#: lib/transport.tcl:89 +msgid "Push Branches" +msgstr "Zweige versenden" + +#: lib/transport.tcl:103 +msgid "Source Branches" +msgstr "Herkunftszweige" + +#: lib/transport.tcl:120 +msgid "Destination Repository" +msgstr "Ziel-Projektarchiv" + +#: lib/transport.tcl:158 +msgid "Transfer Options" +msgstr "Netzwerk-Einstellungen" + +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "" +"Überschreiben von existierenden Zweigen erzwingen (könnte Änderungen löschen)" + +#: lib/transport.tcl:164 +msgid "Use thin pack (for slow network connections)" +msgstr "Kompaktes Datenformat benutzen (für langsame Netzverbindungen)" + +#: lib/transport.tcl:168 +msgid "Include tags" +msgstr "Mit Markierungen übertragen" diff --cc git-gui/po/git-gui.pot index dfa48ae26,000000000..3f139da6c mode 100644,000000..100644 --- a/git-gui/po/git-gui.pot +++ b/git-gui/po/git-gui.pot @@@ -1,1742 -1,0 +1,1778 @@@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2007-11-24 10:36+0100\n" ++"POT-Creation-Date: 2008-02-02 10:14+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: git-gui.sh:41 git-gui.sh:604 git-gui.sh:618 git-gui.sh:631 git-gui.sh:714 +#: git-gui.sh:733 +msgid "git-gui: fatal error" +msgstr "" + +#: git-gui.sh:565 +#, tcl-format +msgid "Invalid font specified in %s:" +msgstr "" + +#: git-gui.sh:590 +msgid "Main Font" +msgstr "" + +#: git-gui.sh:591 +msgid "Diff/Console Font" +msgstr "" + +#: git-gui.sh:605 +msgid "Cannot find git in PATH." +msgstr "" + +#: git-gui.sh:632 +msgid "Cannot parse Git version string:" +msgstr "" + +#: git-gui.sh:650 +#, tcl-format +msgid "" +"Git version cannot be determined.\n" +"\n" +"%s claims it is version '%s'.\n" +"\n" +"%s requires at least Git 1.5.0 or later.\n" +"\n" +"Assume '%s' is version 1.5.0?\n" +msgstr "" + +#: git-gui.sh:888 +msgid "Git directory not found:" +msgstr "" + +#: git-gui.sh:895 +msgid "Cannot move to top of working directory:" +msgstr "" + +#: git-gui.sh:902 +msgid "Cannot use funny .git directory:" +msgstr "" + +#: git-gui.sh:907 +msgid "No working directory" +msgstr "" + +#: git-gui.sh:1054 +msgid "Refreshing file status..." +msgstr "" + +#: git-gui.sh:1119 +msgid "Scanning for modified files ..." +msgstr "" + +#: git-gui.sh:1294 lib/browser.tcl:245 +msgid "Ready." +msgstr "" + +#: git-gui.sh:1560 +msgid "Unmodified" +msgstr "" + +#: git-gui.sh:1562 +msgid "Modified, not staged" +msgstr "" + +#: git-gui.sh:1563 git-gui.sh:1568 +msgid "Staged for commit" +msgstr "" + +#: git-gui.sh:1564 git-gui.sh:1569 +msgid "Portions staged for commit" +msgstr "" + +#: git-gui.sh:1565 git-gui.sh:1570 +msgid "Staged for commit, missing" +msgstr "" + +#: git-gui.sh:1567 +msgid "Untracked, not staged" +msgstr "" + +#: git-gui.sh:1572 +msgid "Missing" +msgstr "" + +#: git-gui.sh:1573 +msgid "Staged for removal" +msgstr "" + +#: git-gui.sh:1574 +msgid "Staged for removal, still present" +msgstr "" + +#: git-gui.sh:1576 git-gui.sh:1577 git-gui.sh:1578 git-gui.sh:1579 +msgid "Requires merge resolution" +msgstr "" + +#: git-gui.sh:1614 +msgid "Starting gitk... please wait..." +msgstr "" + +#: git-gui.sh:1623 +#, tcl-format +msgid "" +"Unable to start gitk:\n" +"\n" +"%s does not exist" +msgstr "" + +#: git-gui.sh:1823 lib/choose_repository.tcl:35 +msgid "Repository" +msgstr "" + +#: git-gui.sh:1824 +msgid "Edit" +msgstr "" + +#: git-gui.sh:1826 lib/choose_rev.tcl:560 +msgid "Branch" +msgstr "" + +#: git-gui.sh:1829 lib/choose_rev.tcl:547 +msgid "Commit@@noun" +msgstr "" + +#: git-gui.sh:1832 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168 +msgid "Merge" +msgstr "" + +#: git-gui.sh:1833 lib/choose_rev.tcl:556 +msgid "Remote" +msgstr "" + +#: git-gui.sh:1842 +msgid "Browse Current Branch's Files" +msgstr "" + +#: git-gui.sh:1846 +msgid "Browse Branch Files..." +msgstr "" + +#: git-gui.sh:1851 +msgid "Visualize Current Branch's History" +msgstr "" + +#: git-gui.sh:1855 +msgid "Visualize All Branch History" +msgstr "" + +#: git-gui.sh:1862 +#, tcl-format +msgid "Browse %s's Files" +msgstr "" + +#: git-gui.sh:1864 +#, tcl-format +msgid "Visualize %s's History" +msgstr "" + +#: git-gui.sh:1869 lib/database.tcl:27 lib/database.tcl:67 +msgid "Database Statistics" +msgstr "" + +#: git-gui.sh:1872 lib/database.tcl:34 +msgid "Compress Database" +msgstr "" + +#: git-gui.sh:1875 +msgid "Verify Database" +msgstr "" + +#: git-gui.sh:1882 git-gui.sh:1886 git-gui.sh:1890 lib/shortcut.tcl:7 +#: lib/shortcut.tcl:39 lib/shortcut.tcl:71 +msgid "Create Desktop Icon" +msgstr "" + +#: git-gui.sh:1895 lib/choose_repository.tcl:176 lib/choose_repository.tcl:184 +msgid "Quit" +msgstr "" + +#: git-gui.sh:1902 +msgid "Undo" +msgstr "" + +#: git-gui.sh:1905 +msgid "Redo" +msgstr "" + +#: git-gui.sh:1909 git-gui.sh:2403 +msgid "Cut" +msgstr "" + +#: git-gui.sh:1912 git-gui.sh:2406 git-gui.sh:2477 git-gui.sh:2549 +#: lib/console.tcl:67 +msgid "Copy" +msgstr "" + +#: git-gui.sh:1915 git-gui.sh:2409 +msgid "Paste" +msgstr "" + +#: git-gui.sh:1918 git-gui.sh:2412 lib/branch_delete.tcl:26 +#: lib/remote_branch_delete.tcl:38 +msgid "Delete" +msgstr "" + +#: git-gui.sh:1922 git-gui.sh:2416 git-gui.sh:2553 lib/console.tcl:69 +msgid "Select All" +msgstr "" + +#: git-gui.sh:1931 +msgid "Create..." +msgstr "" + +#: git-gui.sh:1937 +msgid "Checkout..." +msgstr "" + +#: git-gui.sh:1943 +msgid "Rename..." +msgstr "" + +#: git-gui.sh:1948 git-gui.sh:2048 +msgid "Delete..." +msgstr "" + +#: git-gui.sh:1953 +msgid "Reset..." +msgstr "" + +#: git-gui.sh:1965 git-gui.sh:2350 +msgid "New Commit" +msgstr "" + +#: git-gui.sh:1973 git-gui.sh:2357 +msgid "Amend Last Commit" +msgstr "" + +#: git-gui.sh:1982 git-gui.sh:2317 lib/remote_branch_delete.tcl:99 +msgid "Rescan" +msgstr "" + +#: git-gui.sh:1988 +msgid "Stage To Commit" +msgstr "" + +#: git-gui.sh:1994 +msgid "Stage Changed Files To Commit" +msgstr "" + +#: git-gui.sh:2000 +msgid "Unstage From Commit" +msgstr "" + +#: git-gui.sh:2005 lib/index.tcl:393 +msgid "Revert Changes" +msgstr "" + +#: git-gui.sh:2012 git-gui.sh:2329 git-gui.sh:2427 +msgid "Sign Off" +msgstr "" + +#: git-gui.sh:2016 git-gui.sh:2333 +msgid "Commit@@verb" +msgstr "" + +#: git-gui.sh:2027 +msgid "Local Merge..." +msgstr "" + +#: git-gui.sh:2032 +msgid "Abort Merge..." +msgstr "" + +#: git-gui.sh:2044 +msgid "Push..." +msgstr "" + +#: git-gui.sh:2055 lib/choose_repository.tcl:40 +msgid "Apple" +msgstr "" + +#: git-gui.sh:2058 git-gui.sh:2080 lib/about.tcl:13 +#: lib/choose_repository.tcl:43 lib/choose_repository.tcl:49 +#, tcl-format +msgid "About %s" +msgstr "" + +#: git-gui.sh:2062 +msgid "Preferences..." +msgstr "" + +#: git-gui.sh:2070 git-gui.sh:2595 +msgid "Options..." +msgstr "" + +#: git-gui.sh:2076 lib/choose_repository.tcl:46 +msgid "Help" +msgstr "" + +#: git-gui.sh:2117 +msgid "Online Documentation" +msgstr "" + +#: git-gui.sh:2201 +#, tcl-format +msgid "fatal: cannot stat path %s: No such file or directory" +msgstr "" + +#: git-gui.sh:2234 +msgid "Current Branch:" +msgstr "" + +#: git-gui.sh:2255 +msgid "Staged Changes (Will Commit)" +msgstr "" + +#: git-gui.sh:2274 +msgid "Unstaged Changes" +msgstr "" + +#: git-gui.sh:2323 +msgid "Stage Changed" +msgstr "" + +#: git-gui.sh:2339 lib/transport.tcl:93 lib/transport.tcl:182 +msgid "Push" +msgstr "" + +#: git-gui.sh:2369 +msgid "Initial Commit Message:" +msgstr "" + +#: git-gui.sh:2370 +msgid "Amended Commit Message:" +msgstr "" + +#: git-gui.sh:2371 +msgid "Amended Initial Commit Message:" +msgstr "" + +#: git-gui.sh:2372 +msgid "Amended Merge Commit Message:" +msgstr "" + +#: git-gui.sh:2373 +msgid "Merge Commit Message:" +msgstr "" + +#: git-gui.sh:2374 +msgid "Commit Message:" +msgstr "" + +#: git-gui.sh:2419 git-gui.sh:2557 lib/console.tcl:71 +msgid "Copy All" +msgstr "" + +#: git-gui.sh:2443 lib/blame.tcl:104 +msgid "File:" +msgstr "" + - #: git-gui.sh:2545 - msgid "Refresh" ++#: git-gui.sh:2573 ++msgid "Apply/Reverse Hunk" +msgstr "" + - #: git-gui.sh:2566 - msgid "Apply/Reverse Hunk" ++#: git-gui.sh:2579 ++msgid "Show Less Context" +msgstr "" + - #: git-gui.sh:2572 - msgid "Decrease Font Size" ++#: git-gui.sh:2586 ++msgid "Show More Context" +msgstr "" + - #: git-gui.sh:2576 - msgid "Increase Font Size" ++#: git-gui.sh:2594 ++msgid "Refresh" +msgstr "" + - #: git-gui.sh:2581 - msgid "Show Less Context" ++#: git-gui.sh:2615 ++msgid "Decrease Font Size" +msgstr "" + - #: git-gui.sh:2588 - msgid "Show More Context" ++#: git-gui.sh:2619 ++msgid "Increase Font Size" +msgstr "" + - #: git-gui.sh:2602 ++#: git-gui.sh:2630 +msgid "Unstage Hunk From Commit" +msgstr "" + +#: git-gui.sh:2604 +msgid "Stage Hunk For Commit" +msgstr "" + +#: git-gui.sh:2623 +msgid "Initializing..." +msgstr "" + +#: git-gui.sh:2718 +#, tcl-format +msgid "" +"Possible environment issues exist.\n" +"\n" +"The following environment variables are probably\n" +"going to be ignored by any Git subprocess run\n" +"by %s:\n" +"\n" +msgstr "" + +#: git-gui.sh:2748 +msgid "" +"\n" +"This is due to a known issue with the\n" +"Tcl binary distributed by Cygwin." +msgstr "" + +#: git-gui.sh:2753 +#, tcl-format +msgid "" +"\n" +"\n" +"A good replacement for %s\n" +"is placing values for the user.name and\n" +"user.email settings into your personal\n" +"~/.gitconfig file.\n" +msgstr "" + +#: lib/about.tcl:25 +msgid "git-gui - a graphical user interface for Git." +msgstr "" + +#: lib/blame.tcl:77 +msgid "File Viewer" +msgstr "" + +#: lib/blame.tcl:81 +msgid "Commit:" +msgstr "" + +#: lib/blame.tcl:249 +msgid "Copy Commit" +msgstr "" + +#: lib/blame.tcl:369 +#, tcl-format +msgid "Reading %s..." +msgstr "" + +#: lib/blame.tcl:473 +msgid "Loading copy/move tracking annotations..." +msgstr "" + +#: lib/blame.tcl:493 +msgid "lines annotated" +msgstr "" + +#: lib/blame.tcl:674 +msgid "Loading original location annotations..." +msgstr "" + +#: lib/blame.tcl:677 +msgid "Annotation complete." +msgstr "" + +#: lib/blame.tcl:731 +msgid "Loading annotation..." +msgstr "" + +#: lib/blame.tcl:787 +msgid "Author:" +msgstr "" + +#: lib/blame.tcl:791 +msgid "Committer:" +msgstr "" + +#: lib/blame.tcl:796 +msgid "Original File:" +msgstr "" + +#: lib/blame.tcl:910 +msgid "Originally By:" +msgstr "" + +#: lib/blame.tcl:916 +msgid "In File:" +msgstr "" + +#: lib/blame.tcl:921 +msgid "Copied Or Moved Here By:" +msgstr "" + +#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19 +msgid "Checkout Branch" +msgstr "" + +#: lib/branch_checkout.tcl:23 +msgid "Checkout" +msgstr "" + +#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35 +#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:281 +#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:172 +#: lib/option.tcl:90 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97 +msgid "Cancel" +msgstr "" + +#: lib/branch_checkout.tcl:32 lib/browser.tcl:286 +msgid "Revision" +msgstr "" + +#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:202 +msgid "Options" +msgstr "" + +#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92 +msgid "Fetch Tracking Branch" +msgstr "" + +#: lib/branch_checkout.tcl:44 +msgid "Detach From Local Branch" +msgstr "" + +#: lib/branch_create.tcl:22 +msgid "Create Branch" +msgstr "" + +#: lib/branch_create.tcl:27 +msgid "Create New Branch" +msgstr "" + +#: lib/branch_create.tcl:31 lib/choose_repository.tcl:375 +msgid "Create" +msgstr "" + +#: lib/branch_create.tcl:40 +msgid "Branch Name" +msgstr "" + +#: lib/branch_create.tcl:43 +msgid "Name:" +msgstr "" + +#: lib/branch_create.tcl:58 +msgid "Match Tracking Branch Name" +msgstr "" + +#: lib/branch_create.tcl:66 +msgid "Starting Revision" +msgstr "" + +#: lib/branch_create.tcl:72 +msgid "Update Existing Branch:" +msgstr "" + +#: lib/branch_create.tcl:75 +msgid "No" +msgstr "" + +#: lib/branch_create.tcl:80 +msgid "Fast Forward Only" +msgstr "" + +#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514 +msgid "Reset" +msgstr "" + +#: lib/branch_create.tcl:97 +msgid "Checkout After Creation" +msgstr "" + +#: lib/branch_create.tcl:131 +msgid "Please select a tracking branch." +msgstr "" + +#: lib/branch_create.tcl:140 +#, tcl-format +msgid "Tracking branch %s is not a branch in the remote repository." +msgstr "" + +#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86 +msgid "Please supply a branch name." +msgstr "" + +#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106 +#, tcl-format +msgid "'%s' is not an acceptable branch name." +msgstr "" + +#: lib/branch_delete.tcl:15 +msgid "Delete Branch" +msgstr "" + +#: lib/branch_delete.tcl:20 +msgid "Delete Local Branch" +msgstr "" + +#: lib/branch_delete.tcl:37 +msgid "Local Branches" +msgstr "" + +#: lib/branch_delete.tcl:52 +msgid "Delete Only If Merged Into" +msgstr "" + +#: lib/branch_delete.tcl:54 +msgid "Always (Do not perform merge test.)" +msgstr "" + +#: lib/branch_delete.tcl:103 +#, tcl-format +msgid "The following branches are not completely merged into %s:" +msgstr "" + +#: lib/branch_delete.tcl:115 +msgid "" +"Recovering deleted branches is difficult. \n" +"\n" +" Delete the selected branches?" +msgstr "" + +#: lib/branch_delete.tcl:141 +#, tcl-format +msgid "" +"Failed to delete branches:\n" +"%s" +msgstr "" + +#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22 +msgid "Rename Branch" +msgstr "" + +#: lib/branch_rename.tcl:26 +msgid "Rename" +msgstr "" + +#: lib/branch_rename.tcl:36 +msgid "Branch:" +msgstr "" + +#: lib/branch_rename.tcl:39 +msgid "New Name:" +msgstr "" + +#: lib/branch_rename.tcl:75 +msgid "Please select a branch to rename." +msgstr "" + +#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179 +#, tcl-format +msgid "Branch '%s' already exists." +msgstr "" + +#: lib/branch_rename.tcl:117 +#, tcl-format +msgid "Failed to rename '%s'." +msgstr "" + +#: lib/browser.tcl:17 +msgid "Starting..." +msgstr "" + +#: lib/browser.tcl:26 +msgid "File Browser" +msgstr "" + +#: lib/browser.tcl:125 lib/browser.tcl:142 +#, tcl-format +msgid "Loading %s..." +msgstr "" + +#: lib/browser.tcl:186 +msgid "[Up To Parent]" +msgstr "" + +#: lib/browser.tcl:266 lib/browser.tcl:272 +msgid "Browse Branch Files" +msgstr "" + +#: lib/browser.tcl:277 lib/choose_repository.tcl:391 +#: lib/choose_repository.tcl:482 lib/choose_repository.tcl:492 +#: lib/choose_repository.tcl:989 +msgid "Browse" +msgstr "" + +#: lib/checkout_op.tcl:79 +#, tcl-format +msgid "Fetching %s from %s" +msgstr "" + +#: lib/checkout_op.tcl:127 +#, tcl-format +msgid "fatal: Cannot resolve %s" +msgstr "" + +#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31 +msgid "Close" +msgstr "" + +#: lib/checkout_op.tcl:169 +#, tcl-format +msgid "Branch '%s' does not exist." +msgstr "" + +#: lib/checkout_op.tcl:206 +#, tcl-format +msgid "" +"Branch '%s' already exists.\n" +"\n" +"It cannot fast-forward to %s.\n" +"A merge is required." +msgstr "" + +#: lib/checkout_op.tcl:220 +#, tcl-format +msgid "Merge strategy '%s' not supported." +msgstr "" + +#: lib/checkout_op.tcl:239 +#, tcl-format +msgid "Failed to update '%s'." +msgstr "" + +#: lib/checkout_op.tcl:251 +msgid "Staging area (index) is already locked." +msgstr "" + +#: lib/checkout_op.tcl:266 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before the current branch can be changed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/checkout_op.tcl:322 +#, tcl-format +msgid "Updating working directory to '%s'..." +msgstr "" + ++#: lib/checkout_op.tcl:323 ++msgid "files checked out" ++msgstr "" ++ +#: lib/checkout_op.tcl:353 +#, tcl-format +msgid "Aborted checkout of '%s' (file level merging is required)." +msgstr "" + +#: lib/checkout_op.tcl:354 +msgid "File level merge required." +msgstr "" + +#: lib/checkout_op.tcl:358 +#, tcl-format +msgid "Staying on branch '%s'." +msgstr "" + +#: lib/checkout_op.tcl:429 +msgid "" +"You are no longer on a local branch.\n" +"\n" +"If you wanted to be on a branch, create one now starting from 'This Detached " +"Checkout'." +msgstr "" + +#: lib/checkout_op.tcl:446 +#, tcl-format +msgid "Checked out '%s'." +msgstr "" + +#: lib/checkout_op.tcl:478 +#, tcl-format +msgid "Resetting '%s' to '%s' will lose the following commits:" +msgstr "" + +#: lib/checkout_op.tcl:500 +msgid "Recovering lost commits may not be easy." +msgstr "" + +#: lib/checkout_op.tcl:505 +#, tcl-format +msgid "Reset '%s'?" +msgstr "" + +#: lib/checkout_op.tcl:510 lib/merge.tcl:164 +msgid "Visualize" +msgstr "" + +#: lib/checkout_op.tcl:578 +#, tcl-format +msgid "" +"Failed to set current branch.\n" +"\n" +"This working directory is only partially switched. We successfully updated " +"your files, but failed to update an internal Git file.\n" +"\n" +"This should not have occurred. %s will now close and give up." +msgstr "" + +#: lib/choose_font.tcl:39 +msgid "Select" +msgstr "" + +#: lib/choose_font.tcl:53 +msgid "Font Family" +msgstr "" + +#: lib/choose_font.tcl:73 +msgid "Font Size" +msgstr "" + +#: lib/choose_font.tcl:90 +msgid "Font Example" +msgstr "" + +#: lib/choose_font.tcl:101 +msgid "" +"This is example text.\n" +"If you like this text, it can be your font." +msgstr "" + +#: lib/choose_repository.tcl:27 +msgid "Git Gui" +msgstr "" + +#: lib/choose_repository.tcl:80 lib/choose_repository.tcl:380 +msgid "Create New Repository" +msgstr "" + +#: lib/choose_repository.tcl:86 +msgid "New..." +msgstr "" + +#: lib/choose_repository.tcl:93 lib/choose_repository.tcl:468 +msgid "Clone Existing Repository" +msgstr "" + +#: lib/choose_repository.tcl:99 +msgid "Clone..." +msgstr "" + +#: lib/choose_repository.tcl:106 lib/choose_repository.tcl:978 +msgid "Open Existing Repository" +msgstr "" + +#: lib/choose_repository.tcl:112 +msgid "Open..." +msgstr "" + +#: lib/choose_repository.tcl:125 +msgid "Recent Repositories" +msgstr "" + +#: lib/choose_repository.tcl:131 +msgid "Open Recent Repository:" +msgstr "" + +#: lib/choose_repository.tcl:294 +#, tcl-format +msgid "Location %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:300 lib/choose_repository.tcl:307 +#: lib/choose_repository.tcl:314 +#, tcl-format +msgid "Failed to create repository %s:" +msgstr "" + +#: lib/choose_repository.tcl:385 lib/choose_repository.tcl:486 +msgid "Directory:" +msgstr "" + +#: lib/choose_repository.tcl:415 lib/choose_repository.tcl:544 +#: lib/choose_repository.tcl:1013 +msgid "Git Repository" +msgstr "" + +#: lib/choose_repository.tcl:430 lib/choose_repository.tcl:437 +#, tcl-format +msgid "Directory %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:442 +#, tcl-format +msgid "File %s already exists." +msgstr "" + +#: lib/choose_repository.tcl:463 +msgid "Clone" +msgstr "" + +#: lib/choose_repository.tcl:476 +msgid "URL:" +msgstr "" + +#: lib/choose_repository.tcl:496 +msgid "Clone Type:" +msgstr "" + +#: lib/choose_repository.tcl:502 +msgid "Standard (Fast, Semi-Redundant, Hardlinks)" +msgstr "" + +#: lib/choose_repository.tcl:508 +msgid "Full Copy (Slower, Redundant Backup)" +msgstr "" + +#: lib/choose_repository.tcl:514 +msgid "Shared (Fastest, Not Recommended, No Backup)" +msgstr "" + +#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597 +#: lib/choose_repository.tcl:738 lib/choose_repository.tcl:808 +#: lib/choose_repository.tcl:1019 lib/choose_repository.tcl:1027 +#, tcl-format +msgid "Not a Git repository: %s" +msgstr "" + +#: lib/choose_repository.tcl:586 +msgid "Standard only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:590 +msgid "Shared only available for local repository." +msgstr "" + +#: lib/choose_repository.tcl:617 +msgid "Failed to configure origin" +msgstr "" + +#: lib/choose_repository.tcl:629 +msgid "Counting objects" +msgstr "" + +#: lib/choose_repository.tcl:630 +msgid "buckets" +msgstr "" + +#: lib/choose_repository.tcl:654 +#, tcl-format +msgid "Unable to copy objects/info/alternates: %s" +msgstr "" + +#: lib/choose_repository.tcl:690 +#, tcl-format +msgid "Nothing to clone from %s." +msgstr "" + +#: lib/choose_repository.tcl:692 lib/choose_repository.tcl:906 +#: lib/choose_repository.tcl:918 +msgid "The 'master' branch has not been initialized." +msgstr "" + +#: lib/choose_repository.tcl:705 +msgid "Hardlinks are unavailable. Falling back to copying." +msgstr "" + +#: lib/choose_repository.tcl:717 +#, tcl-format +msgid "Cloning from %s" +msgstr "" + +#: lib/choose_repository.tcl:748 +msgid "Copying objects" +msgstr "" + +#: lib/choose_repository.tcl:749 +msgid "KiB" +msgstr "" + +#: lib/choose_repository.tcl:773 +#, tcl-format +msgid "Unable to copy object: %s" +msgstr "" + +#: lib/choose_repository.tcl:783 +msgid "Linking objects" +msgstr "" + +#: lib/choose_repository.tcl:784 +msgid "objects" +msgstr "" + +#: lib/choose_repository.tcl:792 +#, tcl-format +msgid "Unable to hardlink object: %s" +msgstr "" + +#: lib/choose_repository.tcl:847 +msgid "Cannot fetch branches and objects. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:858 +msgid "Cannot fetch tags. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:882 +msgid "Cannot determine HEAD. See console output for details." +msgstr "" + +#: lib/choose_repository.tcl:891 +#, tcl-format +msgid "Unable to cleanup %s" +msgstr "" + +#: lib/choose_repository.tcl:897 +msgid "Clone failed." +msgstr "" + +#: lib/choose_repository.tcl:904 +msgid "No default branch obtained." +msgstr "" + +#: lib/choose_repository.tcl:915 +#, tcl-format +msgid "Cannot resolve %s as a commit." +msgstr "" + +#: lib/choose_repository.tcl:927 +msgid "Creating working directory" +msgstr "" + +#: lib/choose_repository.tcl:928 lib/index.tcl:65 lib/index.tcl:127 +#: lib/index.tcl:193 +msgid "files" +msgstr "" + +#: lib/choose_repository.tcl:957 +msgid "Initial file checkout failed." +msgstr "" + +#: lib/choose_repository.tcl:973 +msgid "Open" +msgstr "" + +#: lib/choose_repository.tcl:983 +msgid "Repository:" +msgstr "" + +#: lib/choose_repository.tcl:1033 +#, tcl-format +msgid "Failed to open repository %s:" +msgstr "" + +#: lib/choose_rev.tcl:53 +msgid "This Detached Checkout" +msgstr "" + +#: lib/choose_rev.tcl:60 +msgid "Revision Expression:" +msgstr "" + +#: lib/choose_rev.tcl:74 +msgid "Local Branch" +msgstr "" + +#: lib/choose_rev.tcl:79 +msgid "Tracking Branch" +msgstr "" + +#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:537 +msgid "Tag" +msgstr "" + +#: lib/choose_rev.tcl:317 +#, tcl-format +msgid "Invalid revision: %s" +msgstr "" + +#: lib/choose_rev.tcl:338 +msgid "No revision selected." +msgstr "" + +#: lib/choose_rev.tcl:346 +msgid "Revision expression is empty." +msgstr "" + +#: lib/choose_rev.tcl:530 +msgid "Updated" +msgstr "" + +#: lib/choose_rev.tcl:558 +msgid "URL" +msgstr "" + +#: lib/commit.tcl:9 +msgid "" +"There is nothing to amend.\n" +"\n" +"You are about to create the initial commit. There is no commit before this " +"to amend.\n" +msgstr "" + +#: lib/commit.tcl:18 +msgid "" +"Cannot amend while merging.\n" +"\n" +"You are currently in the middle of a merge that has not been fully " +"completed. You cannot amend the prior commit unless you first abort the " +"current merge activity.\n" +msgstr "" + +#: lib/commit.tcl:49 +msgid "Error loading commit data for amend:" +msgstr "" + +#: lib/commit.tcl:76 +msgid "Unable to obtain your identity:" +msgstr "" + +#: lib/commit.tcl:81 +msgid "Invalid GIT_COMMITTER_IDENT:" +msgstr "" + +#: lib/commit.tcl:133 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before another commit can be created.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/commit.tcl:154 +#, tcl-format +msgid "" +"Unmerged files cannot be committed.\n" +"\n" +"File %s has merge conflicts. You must resolve them and stage the file " +"before committing.\n" +msgstr "" + +#: lib/commit.tcl:162 +#, tcl-format +msgid "" +"Unknown file state %s detected.\n" +"\n" +"File %s cannot be committed by this program.\n" +msgstr "" + +#: lib/commit.tcl:170 +msgid "" +"No changes to commit.\n" +"\n" +"You must stage at least 1 file before you can commit.\n" +msgstr "" + +#: lib/commit.tcl:183 +msgid "" +"Please supply a commit message.\n" +"\n" +"A good commit message has the following format:\n" +"\n" +"- First line: Describe in one sentence what you did.\n" +"- Second line: Blank\n" +"- Remaining lines: Describe why this change is good.\n" +msgstr "" + - #: lib/commit.tcl:257 ++#: lib/commit.tcl:207 ++#, tcl-format ++msgid "warning: Tcl does not support encoding '%s'." ++msgstr "" ++ ++#: lib/commit.tcl:221 ++msgid "Calling pre-commit hook..." ++msgstr "" ++ ++#: lib/commit.tcl:236 ++msgid "Commit declined by pre-commit hook." ++msgstr "" ++ ++#: lib/commit.tcl:259 ++msgid "Calling commit-msg hook..." ++msgstr "" ++ ++#: lib/commit.tcl:274 ++msgid "Commit declined by commit-msg hook." ++msgstr "" ++ ++#: lib/commit.tcl:287 ++msgid "Committing changes..." ++msgstr "" ++ ++#: lib/commit.tcl:303 +msgid "write-tree failed:" +msgstr "" + - #: lib/commit.tcl:275 ++#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368 ++msgid "Commit failed." ++msgstr "" ++ ++#: lib/commit.tcl:321 +#, tcl-format +msgid "Commit %s appears to be corrupt" +msgstr "" + +#: lib/commit.tcl:279 +msgid "" +"No changes to commit.\n" +"\n" +"No files were modified by this commit and it was not a merge commit.\n" +"\n" +"A rescan will be automatically started now.\n" +msgstr "" + +#: lib/commit.tcl:286 +msgid "No changes to commit." +msgstr "" + - #: lib/commit.tcl:303 - #, tcl-format - msgid "warning: Tcl does not support encoding '%s'." - msgstr "" - - #: lib/commit.tcl:317 ++#: lib/commit.tcl:347 +msgid "commit-tree failed:" +msgstr "" + +#: lib/commit.tcl:339 +msgid "update-ref failed:" +msgstr "" + +#: lib/commit.tcl:430 +#, tcl-format +msgid "Created commit %s: %s" +msgstr "" + +#: lib/console.tcl:57 +msgid "Working... please wait..." +msgstr "" + +#: lib/console.tcl:183 +msgid "Success" +msgstr "" + +#: lib/console.tcl:196 +msgid "Error: Command Failed" +msgstr "" + +#: lib/database.tcl:43 +msgid "Number of loose objects" +msgstr "" + +#: lib/database.tcl:44 +msgid "Disk space used by loose objects" +msgstr "" + +#: lib/database.tcl:45 +msgid "Number of packed objects" +msgstr "" + +#: lib/database.tcl:46 +msgid "Number of packs" +msgstr "" + +#: lib/database.tcl:47 +msgid "Disk space used by packed objects" +msgstr "" + +#: lib/database.tcl:48 +msgid "Packed objects waiting for pruning" +msgstr "" + +#: lib/database.tcl:49 +msgid "Garbage files" +msgstr "" + +#: lib/database.tcl:72 +msgid "Compressing the object database" +msgstr "" + +#: lib/database.tcl:83 +msgid "Verifying the object database with fsck-objects" +msgstr "" + +#: lib/database.tcl:108 +#, tcl-format +msgid "" +"This repository currently has approximately %i loose objects.\n" +"\n" +"To maintain optimal performance it is strongly recommended that you compress " +"the database when more than %i loose objects exist.\n" +"\n" +"Compress the database now?" +msgstr "" + +#: lib/date.tcl:25 +#, tcl-format +msgid "Invalid date from Git: %s" +msgstr "" + +#: lib/diff.tcl:42 +#, tcl-format +msgid "" +"No differences detected.\n" +"\n" +"%s has no changes.\n" +"\n" +"The modification date of this file was updated by another application, but " +"the content within the file was not changed.\n" +"\n" +"A rescan will be automatically started to find other files which may have " +"the same state." +msgstr "" + +#: lib/diff.tcl:81 +#, tcl-format +msgid "Loading diff of %s..." +msgstr "" + +#: lib/diff.tcl:114 lib/diff.tcl:184 +#, tcl-format +msgid "Unable to display %s" +msgstr "" + +#: lib/diff.tcl:115 +msgid "Error loading file:" +msgstr "" + +#: lib/diff.tcl:122 +msgid "Git Repository (subproject)" +msgstr "" + +#: lib/diff.tcl:134 +msgid "* Binary file (not showing content)." +msgstr "" + +#: lib/diff.tcl:185 +msgid "Error loading diff:" +msgstr "" + +#: lib/diff.tcl:302 +msgid "Failed to unstage selected hunk." +msgstr "" + +#: lib/diff.tcl:309 +msgid "Failed to stage selected hunk." +msgstr "" + +#: lib/error.tcl:12 lib/error.tcl:102 +msgid "error" +msgstr "" + +#: lib/error.tcl:28 +msgid "warning" +msgstr "" + +#: lib/error.tcl:81 +msgid "You must correct the above errors before committing." +msgstr "" + +#: lib/index.tcl:6 +msgid "Unable to unlock the index." +msgstr "" + +#: lib/index.tcl:15 +msgid "Index Error" +msgstr "" + +#: lib/index.tcl:21 +msgid "" +"Updating the Git index failed. A rescan will be automatically started to " +"resynchronize git-gui." +msgstr "" + +#: lib/index.tcl:27 +msgid "Continue" +msgstr "" + +#: lib/index.tcl:31 +msgid "Unlock Index" +msgstr "" + +#: lib/index.tcl:282 +#, tcl-format +msgid "Unstaging %s from commit" +msgstr "" + ++#: lib/index.tcl:313 ++msgid "Ready to commit." ++msgstr "" ++ +#: lib/index.tcl:326 +#, tcl-format +msgid "Adding %s" +msgstr "" + +#: lib/index.tcl:381 +#, tcl-format +msgid "Revert changes in file %s?" +msgstr "" + +#: lib/index.tcl:383 +#, tcl-format +msgid "Revert changes in these %i files?" +msgstr "" + +#: lib/index.tcl:389 +msgid "Any unstaged changes will be permanently lost by the revert." +msgstr "" + +#: lib/index.tcl:392 +msgid "Do Nothing" +msgstr "" + +#: lib/merge.tcl:13 +msgid "" +"Cannot merge while amending.\n" +"\n" +"You must finish amending this commit before starting any type of merge.\n" +msgstr "" + +#: lib/merge.tcl:27 +msgid "" +"Last scanned state does not match repository state.\n" +"\n" +"Another Git program has modified this repository since the last scan. A " +"rescan must be performed before a merge can be performed.\n" +"\n" +"The rescan will be automatically started now.\n" +msgstr "" + +#: lib/merge.tcl:44 +#, tcl-format +msgid "" +"You are in the middle of a conflicted merge.\n" +"\n" +"File %s has merge conflicts.\n" +"\n" +"You must resolve them, stage the file, and commit to complete the current " +"merge. Only then can you begin another merge.\n" +msgstr "" + +#: lib/merge.tcl:54 +#, tcl-format +msgid "" +"You are in the middle of a change.\n" +"\n" +"File %s is modified.\n" +"\n" +"You should complete the current commit before starting a merge. Doing so " +"will help you abort a failed merge, should the need arise.\n" +msgstr "" + +#: lib/merge.tcl:106 +#, tcl-format +msgid "%s of %s" +msgstr "" + +#: lib/merge.tcl:119 +#, tcl-format +msgid "Merging %s and %s" +msgstr "" + +#: lib/merge.tcl:131 +msgid "Merge completed successfully." +msgstr "" + +#: lib/merge.tcl:133 +msgid "Merge failed. Conflict resolution is required." +msgstr "" + +#: lib/merge.tcl:158 +#, tcl-format +msgid "Merge Into %s" +msgstr "" + +#: lib/merge.tcl:177 +msgid "Revision To Merge" +msgstr "" + +#: lib/merge.tcl:212 +msgid "" +"Cannot abort while amending.\n" +"\n" +"You must finish amending this commit.\n" +msgstr "" + +#: lib/merge.tcl:222 +msgid "" +"Abort merge?\n" +"\n" +"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with aborting the current merge?" +msgstr "" + +#: lib/merge.tcl:228 +msgid "" +"Reset changes?\n" +"\n" +"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n" +"\n" +"Continue with resetting the current changes?" +msgstr "" + +#: lib/merge.tcl:239 +msgid "Aborting" +msgstr "" + - #: lib/merge.tcl:266 ++#: lib/merge.tcl:238 ++msgid "files reset" ++msgstr "" ++ ++#: lib/merge.tcl:265 +msgid "Abort failed." +msgstr "" + +#: lib/merge.tcl:268 +msgid "Abort completed. Ready." +msgstr "" + +#: lib/option.tcl:82 +msgid "Restore Defaults" +msgstr "" + +#: lib/option.tcl:86 +msgid "Save" +msgstr "" + +#: lib/option.tcl:96 +#, tcl-format +msgid "%s Repository" +msgstr "" + +#: lib/option.tcl:97 +msgid "Global (All Repositories)" +msgstr "" + +#: lib/option.tcl:103 +msgid "User Name" +msgstr "" + +#: lib/option.tcl:104 +msgid "Email Address" +msgstr "" + +#: lib/option.tcl:106 +msgid "Summarize Merge Commits" +msgstr "" + +#: lib/option.tcl:107 +msgid "Merge Verbosity" +msgstr "" + +#: lib/option.tcl:108 +msgid "Show Diffstat After Merge" +msgstr "" + +#: lib/option.tcl:110 +msgid "Trust File Modification Timestamps" +msgstr "" + +#: lib/option.tcl:111 +msgid "Prune Tracking Branches During Fetch" +msgstr "" + +#: lib/option.tcl:112 +msgid "Match Tracking Branches" +msgstr "" + +#: lib/option.tcl:113 +msgid "Number of Diff Context Lines" +msgstr "" + +#: lib/option.tcl:114 +msgid "New Branch Name Template" +msgstr "" + +#: lib/option.tcl:176 +msgid "Change Font" +msgstr "" + +#: lib/option.tcl:180 +#, tcl-format +msgid "Choose %s" +msgstr "" + +#: lib/option.tcl:186 +msgid "pt." +msgstr "" + +#: lib/option.tcl:200 +msgid "Preferences" +msgstr "" + +#: lib/option.tcl:235 +msgid "Failed to completely save options:" +msgstr "" + +#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34 +msgid "Delete Remote Branch" +msgstr "" + +#: lib/remote_branch_delete.tcl:47 +msgid "From Repository" +msgstr "" + +#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123 +msgid "Remote:" +msgstr "" + +#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138 +msgid "Arbitrary URL:" +msgstr "" + +#: lib/remote_branch_delete.tcl:84 +msgid "Branches" +msgstr "" + +#: lib/remote_branch_delete.tcl:109 +msgid "Delete Only If" +msgstr "" + +#: lib/remote_branch_delete.tcl:111 +msgid "Merged Into:" +msgstr "" + +#: lib/remote_branch_delete.tcl:119 +msgid "Always (Do not perform merge checks)" +msgstr "" + +#: lib/remote_branch_delete.tcl:152 +msgid "A branch is required for 'Merged Into'." +msgstr "" + +#: lib/remote_branch_delete.tcl:184 +#, tcl-format +msgid "" +"The following branches are not completely merged into %s:\n" +"\n" +" - %s" +msgstr "" + +#: lib/remote_branch_delete.tcl:189 +#, tcl-format +msgid "" +"One or more of the merge tests failed because you have not fetched the " +"necessary commits. Try fetching from %s first." +msgstr "" + +#: lib/remote_branch_delete.tcl:207 +msgid "Please select one or more branches to delete." +msgstr "" + +#: lib/remote_branch_delete.tcl:216 +msgid "" +"Recovering deleted branches is difficult.\n" +"\n" +"Delete the selected branches?" +msgstr "" + +#: lib/remote_branch_delete.tcl:226 +#, tcl-format +msgid "Deleting branches from %s" +msgstr "" + +#: lib/remote_branch_delete.tcl:286 +msgid "No repository selected." +msgstr "" + +#: lib/remote_branch_delete.tcl:291 +#, tcl-format +msgid "Scanning %s..." +msgstr "" + +#: lib/remote.tcl:165 +msgid "Prune from" +msgstr "" + +#: lib/remote.tcl:170 +msgid "Fetch from" +msgstr "" + +#: lib/remote.tcl:213 +msgid "Push to" +msgstr "" + +#: lib/shortcut.tcl:20 lib/shortcut.tcl:61 +msgid "Cannot write shortcut:" +msgstr "" + +#: lib/shortcut.tcl:136 +msgid "Cannot write icon:" +msgstr "" + +#: lib/status_bar.tcl:83 +#, tcl-format +msgid "%s ... %*i of %*i %s (%3i%%)" +msgstr "" + +#: lib/transport.tcl:6 +#, tcl-format +msgid "fetch %s" +msgstr "" + +#: lib/transport.tcl:7 +#, tcl-format +msgid "Fetching new changes from %s" +msgstr "" + +#: lib/transport.tcl:18 +#, tcl-format +msgid "remote prune %s" +msgstr "" + +#: lib/transport.tcl:19 +#, tcl-format +msgid "Pruning tracking branches deleted from %s" +msgstr "" + +#: lib/transport.tcl:25 lib/transport.tcl:71 +#, tcl-format +msgid "push %s" +msgstr "" + +#: lib/transport.tcl:26 +#, tcl-format +msgid "Pushing changes to %s" +msgstr "" + +#: lib/transport.tcl:72 +#, tcl-format +msgid "Pushing %s %s to %s" +msgstr "" + +#: lib/transport.tcl:89 +msgid "Push Branches" +msgstr "" + +#: lib/transport.tcl:103 +msgid "Source Branches" +msgstr "" + +#: lib/transport.tcl:120 +msgid "Destination Repository" +msgstr "" + +#: lib/transport.tcl:158 +msgid "Transfer Options" +msgstr "" + +#: lib/transport.tcl:160 +msgid "Force overwrite existing branch (may discard changes)" +msgstr "" + +#: lib/transport.tcl:164 +msgid "Use thin pack (for slow network connections)" +msgstr "" + +#: lib/transport.tcl:168 +msgid "Include tags" +msgstr ""