git-gui: Support a native Mac OS X application bundle
authorShawn O. Pearce <spearce@spearce.org>
Thu, 27 Sep 2007 06:30:51 +0000 (02:30 -0400)
committerShawn O. Pearce <spearce@spearce.org>
Fri, 28 Sep 2007 02:17:00 +0000 (22:17 -0400)
If we are building on Darwin (sometimes known as Mac OS X) and we
find the Mac OS X Tk.framework in the expected location we build
a proper Mac OS X application bundle with icons and info list.  The
git-gui and git-citool commands are modified to be very short shell
scripts that just execute the application bundle, starting Tk with
our own info list and icon set.

Although the Makefile change here is rather large it makes for a
much more pleasant user experience on Mac OS X as git-gui now has
its own icon on the dock, in the standard tk_messageBox dialogs,
and the application name now says "Git Gui" instead of "Wish" in
locations such as the menu bar and the alt-tab window.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
.gitignore
Makefile
macosx/AppMain.tcl [new file with mode: 0644]
macosx/Info.plist [new file with mode: 0644]
macosx/git-gui.icns [new file with mode: 0644]

index 020b86deae9ee5e258ac42b2b44c8baae7015938..a7cfd6d5a016b9c0089fcd3409c25cfce5986271 100644 (file)
@@ -1,5 +1,7 @@
+.DS_Store
+Git Gui.app*
+git-gui.tcl
 GIT-VERSION-FILE
 GIT-GUI-VARS
-git-citool
 git-gui
 lib/tclIndex
index ea83263406b06b87074ff803f93e20e552f10d05..818a0ab45ce02d6c90522213ec9cb4dd45bd83be 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,11 +11,12 @@ 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')
 
 SCRIPT_SH = git-gui.sh
+GITGUI_MAIN := git-gui
 GITGUI_BUILT_INS = git-citool
-ALL_PROGRAMS = $(GITGUI_BUILT_INS) $(patsubst %.sh,%,$(SCRIPT_SH))
 ALL_LIBFILES = $(wildcard lib/*.tcl)
 PRELOAD_FILES = lib/class.tcl
 
@@ -35,7 +36,7 @@ ifndef INSTALL
        INSTALL = install
 endif
 
-RM_F      ?= rm -f
+RM_RF     ?= rm -rf
 RMDIR     ?= rmdir
 
 INSTALL_D0 = $(INSTALL) -d -m755 # space is required here
@@ -44,6 +45,8 @@ INSTALL_R0 = $(INSTALL) -m644 # space is required here
 INSTALL_R1 =
 INSTALL_X0 = $(INSTALL) -m755 # 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 =
@@ -51,14 +54,13 @@ INSTALL_L3 =
 
 REMOVE_D0  = $(RMDIR) # space is required here
 REMOVE_D1  = || true
-REMOVE_F0  = $(RM_F) # space is required here
+REMOVE_F0  = $(RM_RF) # space is required here
 REMOVE_F1  =
 CLEAN_DST  = true
 
 ifndef V
        QUIET          = @
-       QUIET_GEN      = $(QUIET)echo '   ' GEN $@ &&
-       QUIET_BUILT_IN = $(QUIET)echo '   ' BUILTIN $@ &&
+       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'
@@ -70,6 +72,8 @@ ifndef V
        INSTALL_R1 = && echo '   ' INSTALL 644 `basename $$src` && $(INSTALL) -m644 $$src
        INSTALL_X0 = src=
        INSTALL_X1 = && echo '   ' INSTALL 755 `basename $$src` && $(INSTALL) -m755 $$src
+       INSTALL_A0 = src=
+       INSTALL_A1 = && echo '   ' INSTALL '   ' `basename "$$src"` && find "$$src" | cpio -pud
 
        INSTALL_L0 = dst=
        INSTALL_L1 = && src=
@@ -80,15 +84,15 @@ ifndef V
        REMOVE_D0 = dir=
        REMOVE_D1 = && echo ' ' REMOVE $$dir && test -d "$$dir" && $(RMDIR) "$$dir" || true
        REMOVE_F0 = dst=
-       REMOVE_F1 = && echo '   ' REMOVE `basename "$$dst"` && $(RM_F) "$$dst"
+       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 ($(findstring $(MAKEFLAGS),s),s)
 QUIET_GEN =
-QUIET_BUILT_IN =
 endif
 
 DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
@@ -105,6 +109,7 @@ exedir     = $(dir $(gitexecdir))share/git-gui/lib
 
 GITGUI_SCRIPT   := $$0
 GITGUI_RELATIVE :=
+GITGUI_MACOSXAPP :=
 
 ifeq ($(exedir),$(gg_libdir))
        GITGUI_RELATIVE := 1
@@ -116,8 +121,51 @@ ifeq ($(uname_O),Cygwin)
                gg_libdir := $(shell cygpath --windows --absolute "$(gg_libdir)")
        endif
 endif
+ifeq ($(uname_S),Darwin)
+       ifeq ($(shell test -d $(TKFRAMEWORK) && echo y),y)
+               GITGUI_MACOSXAPP := YesPlease
+       endif
+endif
 
-$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
+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'\' \
+               '"$$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
+       $(QUIET_GEN)rm -rf '$@' '$@'+ && \
+       mkdir -p '$@'+/Contents/MacOS && \
+       mkdir -p '$@'+/Contents/Resources/Scripts && \
+       cp '$(subst ','\'',$(TKFRAMEWORK))/Contents/MacOS/Wish' \
+               '$@'+/Contents/MacOS && \
+       cp macosx/git-gui.icns '$@'+/Contents/Resources && \
+       sed -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/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
+
+$(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)|' \
@@ -125,13 +173,10 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
                -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
                -e 's|@@GITGUI_RELATIVE@@|$(GITGUI_RELATIVE)|' \
                -e '$(GITGUI_RELATIVE)s|@@GITGUI_LIBDIR@@|$(libdir_SED)|' \
-               $@.sh >$@+ && \
+               git-gui.sh >$@+ && \
        chmod +x $@+ && \
        mv $@+ $@
 
-$(GITGUI_BUILT_INS): git-gui
-       $(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@
-
 XGETTEXT   ?= xgettext
 ifdef NO_MSGFMT
        MSGFMT ?= $(TCL_PATH) po/po2msg.sh
@@ -152,7 +197,7 @@ update-po:: $(PO_TEMPLATE)
 $(ALL_MSGFILES): %.msg : %.po
        $(QUIET_MSGFMT0)$(MSGFMT) --statistics --tcl $< -l $(basename $(notdir $<)) -d $(dir $@) $(QUIET_MSGFMT1)
 
-lib/tclIndex: $(ALL_LIBFILES)
+lib/tclIndex: $(ALL_LIBFILES) GIT-GUI-VARS
        $(QUIET_INDEX)if echo \
          $(foreach p,$(PRELOAD_FILES),source $p\;) \
          auto_mkindex lib '*.tcl' \
@@ -166,16 +211,13 @@ lib/tclIndex: $(ALL_LIBFILES)
         echo >>$@ ; \
        fi
 
-# These can record GITGUI_VERSION
-$(patsubst %.sh,%,$(SCRIPT_SH)): GIT-VERSION-FILE GIT-GUI-VARS
-lib/tclIndex: GIT-GUI-VARS
-
 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
@@ -185,7 +227,10 @@ GIT-GUI-VARS: .FORCE-GIT-GUI-VARS
                echo 1>$@ "$$VARS"; \
        fi
 
-all:: $(ALL_PROGRAMS) lib/tclIndex $(ALL_MSGFILES)
+ifdef GITGUI_MACOSXAPP
+all:: git-gui Git\ Gui.app
+endif
+all:: $(GITGUI_MAIN) lib/tclIndex $(ALL_MSGFILES)
 
 install: all
        $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)
@@ -194,6 +239,10 @@ install: all
        $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(libdir_SQ)' $(INSTALL_D1)
        $(QUIET)$(INSTALL_R0)lib/tclIndex $(INSTALL_R1) '$(DESTDIR_SQ)$(libdir_SQ)'
        $(QUIET)$(INSTALL_R0)lib/git-gui.ico $(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), $(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
@@ -205,6 +254,10 @@ uninstall:
        $(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(libdir_SQ)'
        $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/tclIndex $(REMOVE_F1)
        $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(libdir_SQ)'/git-gui.ico $(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), $(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
@@ -218,8 +271,11 @@ dist-version:
        @echo $(GITGUI_VERSION) > $(TARDIR)/version
 
 clean::
-       rm -f $(ALL_PROGRAMS) lib/tclIndex po/*.msg
-       rm -f GIT-VERSION-FILE GIT-GUI-VARS
+       $(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
 
 .PHONY: all install uninstall dist-version clean
 .PHONY: .FORCE-GIT-VERSION-FILE
diff --git a/macosx/AppMain.tcl b/macosx/AppMain.tcl
new file mode 100644 (file)
index 0000000..41ca08e
--- /dev/null
@@ -0,0 +1,22 @@
+set gitexecdir {@@gitexecdir@@}
+set gitguilib  {@@GITGUI_LIBDIR@@}
+set env(PATH) "$gitexecdir:$env(PATH)"
+
+if {[string first -psn [lindex $argv 0]] == 0} {
+       lset argv 0 [file join $gitexecdir git-gui]
+}
+
+if {[file tail [lindex $argv 0]] eq {gitk}} {
+       set argv0 [file join $gitexecdir gitk]
+       set AppMain_source $argv0
+} else {
+       set argv0 [file join $gitexecdir [file tail [lindex $argv 0]]]
+       set AppMain_source [file join $gitguilib git-gui.tcl]
+       if {[pwd] eq {/}} {
+               cd $env(HOME)
+       }
+}
+
+unset gitexecdir gitguilib
+set argv [lrange $argv 1 end]
+source $AppMain_source
diff --git a/macosx/Info.plist b/macosx/Info.plist
new file mode 100644 (file)
index 0000000..99913ec
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>Wish</string>
+       <key>CFBundleGetInfoString</key>
+       <string>Git Gui @@GITGUI_VERSION@@ © 2006-2007 Shawn Pearce, et. al.</string>
+       <key>CFBundleIconFile</key>
+       <string>git-gui.icns</string>
+       <key>CFBundleIdentifier</key>
+       <string>cz.or.repo.git-gui</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>Git Gui</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>@@GITGUI_VERSION@@</string>
+       <key>CFBundleSignature</key>
+       <string>GITg</string>
+       <key>CFBundleVersion</key>
+       <string>@@GITGUI_VERSION@@</string>
+</dict>
+</plist>
diff --git a/macosx/git-gui.icns b/macosx/git-gui.icns
new file mode 100644 (file)
index 0000000..77d88a7
Binary files /dev/null and b/macosx/git-gui.icns differ