Skip to content

Commit 1a75f6b

Browse files
vdyeldennington
authored andcommitted
release: add Mac OSX installer build
- include `scalar` - build signed .dmg & .pkg for target OS version 10.6 - upload artifacts to workflow Co-authored-by: Lessley Dennington <[email protected]>
1 parent 175bd6e commit 1a75f6b

File tree

10 files changed

+581
-0
lines changed

10 files changed

+581
-0
lines changed

.github/macos-installer/Makefile

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
SHELL := /bin/bash
2+
SUDO := sudo
3+
C_INCLUDE_PATH := /usr/include
4+
CPLUS_INCLUDE_PATH := /usr/include
5+
LD_LIBRARY_PATH := /usr/lib
6+
7+
OSX_VERSION := $(shell sw_vers -productVersion)
8+
TARGET_FLAGS := -mmacosx-version-min=$(OSX_VERSION) -DMACOSX_DEPLOYMENT_TARGET=$(OSX_VERSION)
9+
10+
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
11+
12+
ARCH_UNIV := universal
13+
ARCH_FLAGS := -arch x86_64 -arch arm64
14+
15+
CFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS)
16+
LDFLAGS := $(TARGET_FLAGS) $(ARCH_FLAGS)
17+
18+
PREFIX := /usr/local
19+
GIT_PREFIX := $(PREFIX)/git
20+
21+
# Replace -rc with .rc in the version string
22+
# This is to ensure compatibility with the format as generated by GIT-VERSION-GEN
23+
ORIGINAL_VERSION := $(VERSION)
24+
VERSION := $(shell echo $(ORIGINAL_VERSION) | sed 's/-rc/.rc/g')
25+
26+
BUILD_DIR := $(GITHUB_WORKSPACE)/payload
27+
DESTDIR := $(PWD)/stage/git-$(ARCH_UNIV)-$(VERSION)
28+
ARTIFACTDIR := build-artifacts
29+
SUBMAKE := $(MAKE) C_INCLUDE_PATH="$(C_INCLUDE_PATH)" CPLUS_INCLUDE_PATH="$(CPLUS_INCLUDE_PATH)" LD_LIBRARY_PATH="$(LD_LIBRARY_PATH)" TARGET_FLAGS="$(TARGET_FLAGS)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" NO_GETTEXT=1 NO_DARWIN_PORTS=1 prefix=$(GIT_PREFIX) DESTDIR=$(DESTDIR)
30+
CORES := $(shell bash -c "sysctl hw.ncpu | awk '{print \$$2}'")
31+
32+
# Guard against environment variables
33+
APPLE_APP_IDENTITY =
34+
APPLE_INSTALLER_IDENTITY =
35+
APPLE_KEYCHAIN_PROFILE =
36+
37+
.PHONY: image pkg payload codesign notarize
38+
39+
.SECONDARY:
40+
41+
$(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV):
42+
rm -f $(BUILD_DIR)/git-$(VERSION)/osx-installed*
43+
mkdir -p $(DESTDIR)$(GIT_PREFIX)
44+
touch $@
45+
46+
$(BUILD_DIR)/git-$(VERSION)/osx-built-keychain:
47+
cd $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain; $(SUBMAKE) CFLAGS="$(CFLAGS) -g -O2 -Wall"
48+
touch $@
49+
50+
$(BUILD_DIR)/git-$(VERSION)/osx-built:
51+
[ -d $(DESTDIR)$(GIT_PREFIX) ] && $(SUDO) rm -rf $(DESTDIR) || echo ok
52+
cd $(BUILD_DIR)/git-$(VERSION); $(SUBMAKE) -j $(CORES) all strip
53+
echo "================"
54+
echo "Dumping Linkage"
55+
cd $(BUILD_DIR)/git-$(VERSION); ./git version
56+
echo "===="
57+
cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git
58+
echo "===="
59+
cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-http-fetch
60+
echo "===="
61+
cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-http-push
62+
echo "===="
63+
cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-remote-http
64+
echo "===="
65+
cd $(BUILD_DIR)/git-$(VERSION); /usr/bin/otool -L ./git-gvfs-helper
66+
echo "================"
67+
touch $@
68+
69+
$(BUILD_DIR)/git-$(VERSION)/osx-installed-bin: $(BUILD_DIR)/git-$(VERSION)/osx-built $(BUILD_DIR)/git-$(VERSION)/osx-built-keychain
70+
cd $(BUILD_DIR)/git-$(VERSION); $(SUBMAKE) install
71+
cp $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain $(DESTDIR)$(GIT_PREFIX)/bin/git-credential-osxkeychain
72+
mkdir -p $(DESTDIR)$(GIT_PREFIX)/contrib/completion
73+
cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-completion.bash $(DESTDIR)$(GIT_PREFIX)/contrib/completion/
74+
cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-completion.zsh $(DESTDIR)$(GIT_PREFIX)/contrib/completion/
75+
cp $(BUILD_DIR)/git-$(VERSION)/contrib/completion/git-prompt.sh $(DESTDIR)$(GIT_PREFIX)/contrib/completion/
76+
# This is needed for Git-Gui, GitK
77+
mkdir -p $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl
78+
[ ! -f $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl/Error.pm ] && cp $(BUILD_DIR)/git-$(VERSION)/perl/private-Error.pm $(DESTDIR)$(GIT_PREFIX)/lib/perl5/site_perl/Error.pm || echo done
79+
touch $@
80+
81+
$(BUILD_DIR)/git-$(VERSION)/osx-installed-man: $(BUILD_DIR)/git-$(VERSION)/osx-installed-bin
82+
mkdir -p $(DESTDIR)$(GIT_PREFIX)/share/man
83+
cp -R $(GITHUB_WORKSPACE)/manpages/ $(DESTDIR)$(GIT_PREFIX)/share/man
84+
touch $@
85+
86+
$(BUILD_DIR)/git-$(VERSION)/osx-built-subtree:
87+
$(SUBMAKE) -C $(BUILD_DIR)/git-$(VERSION)/Documentation asciidoc.conf
88+
cd $(BUILD_DIR)/git-$(VERSION)/contrib/subtree; $(SUBMAKE) XML_CATALOG_FILES="$(XML_CATALOG_FILES)" all git-subtree.1
89+
touch $@
90+
91+
$(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree: $(BUILD_DIR)/git-$(VERSION)/osx-built-subtree
92+
mkdir -p $(DESTDIR)
93+
cd $(BUILD_DIR)/git-$(VERSION)/contrib/subtree; $(SUBMAKE) XML_CATALOG_FILES="$(XML_CATALOG_FILES)" install install-man
94+
touch $@
95+
96+
$(BUILD_DIR)/git-$(VERSION)/osx-installed-assets: $(BUILD_DIR)/git-$(VERSION)/osx-installed-bin
97+
mkdir -p $(DESTDIR)$(GIT_PREFIX)/etc
98+
cat assets/etc/gitconfig.osxkeychain >> $(DESTDIR)$(GIT_PREFIX)/etc/gitconfig
99+
cp assets/uninstall.sh $(DESTDIR)$(GIT_PREFIX)/uninstall.sh
100+
sh -c "echo .DS_Store >> $(DESTDIR)$(GIT_PREFIX)/share/git-core/templates/info/exclude"
101+
102+
symlinks:
103+
mkdir -p $(ARTIFACTDIR)$(PREFIX)/bin
104+
cd $(ARTIFACTDIR)$(PREFIX)/bin; find ../git/bin -type f -exec ln -sf {} \;
105+
for man in man1 man3 man5 man7; do mkdir -p $(ARTIFACTDIR)$(PREFIX)/share/man/$$man; (cd $(ARTIFACTDIR)$(PREFIX)/share/man/$$man; ln -sf ../../../git/share/man/$$man/* ./); done
106+
ruby ../scripts/symlink-git-hardlinks.rb $(ARTIFACTDIR)
107+
touch $@
108+
109+
$(BUILD_DIR)/git-$(VERSION)/osx-installed: $(DESTDIR)$(GIT_PREFIX)/VERSION-$(VERSION)-$(ARCH_UNIV) $(BUILD_DIR)/git-$(VERSION)/osx-installed-man $(BUILD_DIR)/git-$(VERSION)/osx-installed-assets $(BUILD_DIR)/git-$(VERSION)/osx-installed-subtree
110+
find $(DESTDIR)$(GIT_PREFIX) -type d -exec chmod ugo+rx {} \;
111+
find $(DESTDIR)$(GIT_PREFIX) -type f -exec chmod ugo+r {} \;
112+
touch $@
113+
114+
$(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV): $(BUILD_DIR)/git-$(VERSION)/osx-built
115+
File $(BUILD_DIR)/git-$(VERSION)/git
116+
File $(BUILD_DIR)/git-$(VERSION)/contrib/credential/osxkeychain/git-credential-osxkeychain
117+
touch $@
118+
119+
disk-image/VERSION-$(VERSION)-$(ARCH_UNIV):
120+
rm -f disk-image/*.pkg disk-image/VERSION-* disk-image/.DS_Store
121+
mkdir disk-image
122+
touch "$@"
123+
124+
pkg_cmd := pkgbuild --identifier com.git.pkg --version $(VERSION) \
125+
--root $(ARTIFACTDIR)$(PREFIX) --scripts assets/scripts \
126+
--install-location $(PREFIX) --component-plist ./assets/git-components.plist
127+
128+
ifdef APPLE_INSTALLER_IDENTITY
129+
pkg_cmd += --sign "$(APPLE_INSTALLER_IDENTITY)"
130+
endif
131+
132+
pkg_cmd += disk-image/git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).pkg
133+
134+
disk-image/git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).pkg: disk-image/VERSION-$(VERSION)-$(ARCH_UNIV) symlinks
135+
$(pkg_cmd)
136+
137+
git-%-$(ARCH_UNIV).dmg:
138+
hdiutil create git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(ORIGINAL_VERSION) $(ARCH_UNIV)" -ov 2>&1 | tee err || { \
139+
grep "Resource busy" err && \
140+
sleep 5 && \
141+
hdiutil create git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).uncompressed.dmg -fs HFS+ -srcfolder disk-image -volname "Git $(ORIGINAL_VERSION) $(ARCH_UNIV)" -ov; }
142+
hdiutil convert -format UDZO -o $@ git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).uncompressed.dmg
143+
rm -f git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).uncompressed.dmg
144+
145+
payload: $(BUILD_DIR)/git-$(VERSION)/osx-installed $(BUILD_DIR)/git-$(VERSION)/osx-built-assert-$(ARCH_UNIV)
146+
147+
pkg: disk-image/git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).pkg
148+
149+
image: git-$(ORIGINAL_VERSION)-$(ARCH_UNIV).dmg
150+
151+
ifdef APPLE_APP_IDENTITY
152+
codesign:
153+
@$(CURDIR)/../scripts/codesign.sh --payload="build-artifacts/usr/local/git" \
154+
--identity="$(APPLE_APP_IDENTITY)" \
155+
--entitlements="$(CURDIR)/entitlements.xml"
156+
endif
157+
158+
# Notarization can only happen if the package is fully signed
159+
ifdef APPLE_KEYCHAIN_PROFILE
160+
notarize:
161+
@$(CURDIR)/../scripts/notarize.sh \
162+
--package="disk-image/git-$(VERSION)-$(ARCH_UNIV).pkg" \
163+
--keychain-profile="$(APPLE_KEYCHAIN_PROFILE)"
164+
endif
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[credential]
2+
helper = osxkeychain
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<array>
5+
<dict>
6+
<key>BundleHasStrictIdentifier</key>
7+
<true/>
8+
<key>BundleIsRelocatable</key>
9+
<false/>
10+
<key>BundleIsVersionChecked</key>
11+
<true/>
12+
<key>BundleOverwriteAction</key>
13+
<string>upgrade</string>
14+
<key>RootRelativeBundlePath</key>
15+
<string>git/share/git-gui/lib/Git Gui.app</string>
16+
</dict>
17+
</array>
18+
</plist>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/bin/bash
2+
INSTALL_DST="$2"
3+
SCALAR_C_CMD="$INSTALL_DST/git/bin/scalar"
4+
SCALAR_DOTNET_CMD="/usr/local/scalar/scalar"
5+
SCALAR_UNINSTALL_SCRIPT="/usr/local/scalar/uninstall_scalar.sh"
6+
7+
function cleanupScalar()
8+
{
9+
echo "checking whether Scalar was installed"
10+
if [ ! -f "$SCALAR_C_CMD" ]; then
11+
echo "Scalar not installed; exiting..."
12+
return 0
13+
fi
14+
echo "Scalar is installed!"
15+
16+
echo "looking for Scalar.NET"
17+
if [ ! -f "$SCALAR_DOTNET_CMD" ]; then
18+
echo "Scalar.NET not found; exiting..."
19+
return 0
20+
fi
21+
echo "Scalar.NET found!"
22+
23+
currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
24+
25+
# Re-register Scalar.NET repositories with the newly-installed Scalar
26+
for repo in $($SCALAR_DOTNET_CMD list); do
27+
(
28+
PATH="$INSTALL_DST/git/bin:$PATH"
29+
sudo -u "$currentUser" scalar register $repo || \
30+
echo "warning: skipping re-registration of $repo"
31+
)
32+
done
33+
34+
# Uninstall Scalar.NET
35+
echo "removing Scalar.NET"
36+
37+
# Add /usr/local/bin to path - default install location of Homebrew
38+
PATH="/usr/local/bin:$PATH"
39+
if (sudo -u "$currentUser" brew list --cask scalar); then
40+
# Remove from Homebrew
41+
sudo -u "$currentUser" brew remove --cask scalar || echo "warning: Scalar.NET uninstall via Homebrew completed with code $?"
42+
echo "Scalar.NET uninstalled via Homebrew!"
43+
elif (sudo -u "$currentUser" brew list --cask scalar-azrepos); then
44+
sudo -u "$currentUser" brew remove --cask scalar-azrepos || echo "warning: Scalar.NET with GVFS uninstall via Homebrew completed with code $?"
45+
echo "Scalar.NET with GVFS uninstalled via Homebrew!"
46+
elif [ -f $SCALAR_UNINSTALL_SCRIPT ]; then
47+
# If not installed with Homebrew, manually remove package
48+
sudo -S sh $SCALAR_UNINSTALL_SCRIPT || echo "warning: Scalar.NET uninstall completed with code $?"
49+
echo "Scalar.NET uninstalled!"
50+
else
51+
echo "warning: Scalar.NET uninstall script not found"
52+
fi
53+
54+
# Re-create the Scalar symlink, in case it was removed by the Scalar.NET uninstall operation
55+
mkdir -p $INSTALL_DST/bin
56+
/bin/ln -Fs "$SCALAR_C_CMD" "$INSTALL_DST/bin/scalar"
57+
}
58+
59+
# Run Scalar cleanup (will exit if not applicable)
60+
cleanupScalar
61+
62+
exit 0
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/bash -e
2+
if [ ! -r "/usr/local/git" ]; then
3+
echo "Git doesn't appear to be installed via this installer. Aborting"
4+
exit 1
5+
fi
6+
7+
if [ "$1" != "--yes" ]; then
8+
echo "This will uninstall git by removing /usr/local/git/, and symlinks"
9+
printf "Type 'yes' if you are sure you wish to continue: "
10+
read response
11+
else
12+
response="yes"
13+
fi
14+
15+
if [ "$response" == "yes" ]; then
16+
# remove all of the symlinks we've created
17+
pkgutil --files com.git.pkg | grep bin | while read f; do
18+
if [ -L /usr/local/$f ]; then
19+
sudo rm /usr/local/$f
20+
fi
21+
done
22+
23+
# forget receipts.
24+
pkgutil --packages | grep com.git.pkg | xargs -I {} sudo pkgutil --forget {}
25+
echo "Uninstalled"
26+
27+
# The guts all go here.
28+
sudo rm -rf /usr/local/git/
29+
else
30+
echo "Aborted"
31+
exit 1
32+
fi
33+
34+
exit 0
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.security.cs.allow-jit</key>
6+
<true/>
7+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
8+
<true/>
9+
<key>com.apple.security.cs.disable-library-validation</key>
10+
<true/>
11+
</dict>
12+
</plist>

.github/scripts/codesign.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/bin/bash
2+
3+
sign_directory () {
4+
(
5+
cd "$1"
6+
for f in *
7+
do
8+
macho=$(file --mime $f | grep mach)
9+
# Runtime sign dylibs and Mach-O binaries
10+
if [[ $f == *.dylib ]] || [ ! -z "$macho" ];
11+
then
12+
echo "Runtime Signing $f"
13+
codesign -s "$IDENTITY" $f --timestamp --force --options=runtime --entitlements $ENTITLEMENTS_FILE
14+
elif [ -d "$f" ];
15+
then
16+
echo "Signing files in subdirectory $f"
17+
sign_directory "$f"
18+
19+
else
20+
echo "Signing $f"
21+
codesign -s "$IDENTITY" $f --timestamp --force
22+
fi
23+
done
24+
)
25+
}
26+
27+
for i in "$@"
28+
do
29+
case "$i" in
30+
--payload=*)
31+
SIGN_DIR="${i#*=}"
32+
shift # past argument=value
33+
;;
34+
--identity=*)
35+
IDENTITY="${i#*=}"
36+
shift # past argument=value
37+
;;
38+
--entitlements=*)
39+
ENTITLEMENTS_FILE="${i#*=}"
40+
shift # past argument=value
41+
;;
42+
*)
43+
die "unknown option '$i'"
44+
;;
45+
esac
46+
done
47+
48+
if [ -z "$SIGN_DIR" ]; then
49+
echo "error: missing directory argument"
50+
exit 1
51+
elif [ -z "$IDENTITY" ]; then
52+
echo "error: missing signing identity argument"
53+
exit 1
54+
elif [ -z "$ENTITLEMENTS_FILE" ]; then
55+
echo "error: missing entitlements file argument"
56+
exit 1
57+
fi
58+
59+
echo "======== INPUTS ========"
60+
echo "Directory: $SIGN_DIR"
61+
echo "Signing identity: $IDENTITY"
62+
echo "Entitlements: $ENTITLEMENTS_FILE"
63+
echo "======== END INPUTS ========"
64+
65+
sign_directory "$SIGN_DIR"

0 commit comments

Comments
 (0)