Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbb0b580b0 | ||
|
|
dd225b2b8e | ||
|
|
76b01352ac | ||
|
|
fcca8cee38 | ||
|
|
94d1b3fec4 | ||
|
|
4352ae1476 | ||
|
|
846e0b149b | ||
|
|
11ca4dbede | ||
|
|
1d8bdfe491 | ||
|
|
4f5a07822f | ||
|
|
67709dfda6 | ||
|
|
6753226087 | ||
|
|
a3671acf38 | ||
|
|
0aa773a0b3 | ||
|
|
adbc061d0b | ||
|
|
4deae63d43 | ||
|
|
b570006074 | ||
|
|
fd0d8d1adb |
2
NOTES.md
2
NOTES.md
@@ -5,5 +5,5 @@
|
|||||||
|
|
||||||
add a marker for "reboot required"
|
add a marker for "reboot required"
|
||||||
|
|
||||||
dummy22
|
dummy223
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ GITEA_REPO="iKeyMon"
|
|||||||
# optional Sparkle feed helpers:
|
# optional Sparkle feed helpers:
|
||||||
# SPARKLE_EDDSA_KEY_FILE="$HOME/.config/Sparkle/iKeyMon.key"
|
# SPARKLE_EDDSA_KEY_FILE="$HOME/.config/Sparkle/iKeyMon.key"
|
||||||
# SPARKLE_DOWNLOAD_BASE_TEMPLATE="https://git.24unix.net/tracer/iKeyMon/releases/download/v{{VERSION}}"
|
# SPARKLE_DOWNLOAD_BASE_TEMPLATE="https://git.24unix.net/tracer/iKeyMon/releases/download/v{{VERSION}}"
|
||||||
|
# If you prefer SPARKLE_DOWNLOAD_BASE_URL, it will automatically append `/v<version>` for you.
|
||||||
# SPARKLE_APPCAST_OUTPUT="$ROOT_DIR/Sparkle/appcast.xml" # default
|
# SPARKLE_APPCAST_OUTPUT="$ROOT_DIR/Sparkle/appcast.xml" # default
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
14
Sparkle/appcast-local.xml
vendored
Normal file
14
Sparkle/appcast-local.xml
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<rss xmlns:ns0="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
|
||||||
|
<channel>
|
||||||
|
<title>iKeyMon</title>
|
||||||
|
<item>
|
||||||
|
<title>26.0.37 (reinstall)</title>
|
||||||
|
<pubDate>Mon, 08 Dec 2025 18:17:55 +0000</pubDate>
|
||||||
|
<ns0:shortVersionString>26.0.37</ns0:shortVersionString>
|
||||||
|
<ns0:version>1077</ns0:version>
|
||||||
|
<ns0:minimumSystemVersion>15.2</ns0:minimumSystemVersion>
|
||||||
|
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.37/iKeyMon-26.0.37.zip" length="4813994" type="application/octet-stream" ns0:edSignature="C65NrwvB2vwPx9qh/Tu1Xqbfljk1zKaKHVRedOX0nINbhKMbOHerY28HxX0veybUWSFEOu6RGi2yDXumQQVMBA==" />
|
||||||
|
</item>
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
30
Sparkle/appcast.xml
vendored
30
Sparkle/appcast.xml
vendored
@@ -3,28 +3,28 @@
|
|||||||
<channel>
|
<channel>
|
||||||
<title>iKeyMon</title>
|
<title>iKeyMon</title>
|
||||||
<item>
|
<item>
|
||||||
<title>26.0.29</title>
|
<title>26.0.38</title>
|
||||||
<pubDate>Sun, 07 Dec 2025 17:07:32 +0100</pubDate>
|
<pubDate>Mon, 08 Dec 2025 19:31:40 +0100</pubDate>
|
||||||
<sparkle:version>61</sparkle:version>
|
<sparkle:version>79</sparkle:version>
|
||||||
<sparkle:shortVersionString>26.0.29</sparkle:shortVersionString>
|
<sparkle:shortVersionString>26.0.38</sparkle:shortVersionString>
|
||||||
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
||||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/iKeyMon-26.0.29.zip" length="4811507" type="application/octet-stream" sparkle:edSignature="eRH4M8hEYa9gYiyjAVtTpXN3T1o+OGadDRMQu4kHL/dbJ2vj/5pY1+am9/9qG33Qairt3Od/6/WKLyxxs4mWCw=="/>
|
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.38/iKeyMon-26.0.38.zip" length="4813965" type="application/octet-stream" sparkle:edSignature="QQNP/buW11kZJLp3A0atvViRsxkokLt3JT1E/f5Duc+U5ZimC4SiOakk3PsOVTBxhFzYMi75Rbe9xrEDi3pVDg=="/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<title>26.0.28</title>
|
<title>26.0.37</title>
|
||||||
<pubDate>Sun, 07 Dec 2025 17:02:18 +0100</pubDate>
|
<pubDate>Mon, 08 Dec 2025 19:07:34 +0100</pubDate>
|
||||||
<sparkle:version>59</sparkle:version>
|
<sparkle:version>77</sparkle:version>
|
||||||
<sparkle:shortVersionString>26.0.28</sparkle:shortVersionString>
|
<sparkle:shortVersionString>26.0.37</sparkle:shortVersionString>
|
||||||
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
||||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/iKeyMon-26.0.28.zip" length="4811473" type="application/octet-stream" sparkle:edSignature="tF188T0m/j22MStCVbVkrf2JllyZ9wiEmc++kgF4GTKhoAuHURYvT/Euy+ivEodmQ/LzeFolN4lViqaVa3y+DQ=="/>
|
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.37/iKeyMon-26.0.37.zip" length="4813994" type="application/octet-stream" sparkle:edSignature="C65NrwvB2vwPx9qh/Tu1Xqbfljk1zKaKHVRedOX0nINbhKMbOHerY28HxX0veybUWSFEOu6RGi2yDXumQQVMBA=="/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<title>26.0.27</title>
|
<title>26.0.36</title>
|
||||||
<pubDate>Sun, 07 Dec 2025 16:47:33 +0100</pubDate>
|
<pubDate>Mon, 08 Dec 2025 18:45:16 +0100</pubDate>
|
||||||
<sparkle:version>57</sparkle:version>
|
<sparkle:version>75</sparkle:version>
|
||||||
<sparkle:shortVersionString>26.0.27</sparkle:shortVersionString>
|
<sparkle:shortVersionString>26.0.36</sparkle:shortVersionString>
|
||||||
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
<sparkle:minimumSystemVersion>15.2</sparkle:minimumSystemVersion>
|
||||||
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/iKeyMon-26.0.27.zip" length="4811492" type="application/octet-stream" sparkle:edSignature="6aEv0ii20pAkIl8kYWNkHM7+8APyDQtsus0SkF3C7/7q2X73HAsrsskNXjiiq0YF6bPVNAEs5y8G8GpwmerrCw=="/>
|
<enclosure url="https://git.24unix.net/tracer/iKeyMon/releases/download/v26.0.36/iKeyMon-26.0.36.zip" length="4813975" type="application/octet-stream" sparkle:edSignature="RvHYE1oDbjzYMWFcj9RVk7Nzq1k8CDKWY8CfTiKjrkY6r9pDR6KjFoHIimVfizN+JyaGcyUaaqzPlNqUsKx3DA=="/>
|
||||||
</item>
|
</item>
|
||||||
</channel>
|
</channel>
|
||||||
</rss>
|
</rss>
|
||||||
@@ -6,5 +6,7 @@
|
|||||||
<string>https://git.24unix.net/tracer/iKeyMon/raw/branch/master/Sparkle/appcast.xml</string>
|
<string>https://git.24unix.net/tracer/iKeyMon/raw/branch/master/Sparkle/appcast.xml</string>
|
||||||
<key>SUPublicEDKey</key>
|
<key>SUPublicEDKey</key>
|
||||||
<string>EgJgrOGQ79L5me616jA7kDCEOgx+Rg11uYLYLLIyzTI=</string>
|
<string>EgJgrOGQ79L5me616jA7kDCEOgx+Rg11uYLYLLIyzTI=</string>
|
||||||
|
<key>SUEnableInstallerLauncherService</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -4,9 +4,15 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.files.user-selected.read-only</key>
|
<key>com.apple.security.files.user-selected.read-write</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.downloads.read-write</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.network.client</key>
|
<key>com.apple.security.network.client</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.automation.apple-events</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
5221016D2EE5E82700D04952 /* appcast.xml in Resources */ = {isa = PBXBuildFile; fileRef = 5221016B2EE5E82700D04952 /* appcast.xml */; };
|
||||||
52A9B79F2EC8E7EE004DD4A2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B7872EC8E7EE004DD4A2 /* Assets.xcassets */; };
|
52A9B79F2EC8E7EE004DD4A2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B7872EC8E7EE004DD4A2 /* Assets.xcassets */; };
|
||||||
52A9B8222EC8FA8A004DD4A2 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B8212EC8FA8A004DD4A2 /* CHANGELOG.md */; };
|
52A9B8222EC8FA8A004DD4A2 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B8212EC8FA8A004DD4A2 /* CHANGELOG.md */; };
|
||||||
52A9B9722ECF751C004DD4A2 /* signing.env.example in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B9712ECF751C004DD4A2 /* signing.env.example */; };
|
52A9B9722ECF751C004DD4A2 /* signing.env.example in Resources */ = {isa = PBXBuildFile; fileRef = 52A9B9712ECF751C004DD4A2 /* signing.env.example */; };
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
5203C24D2D997D2800576D4A /* iKeyMon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iKeyMon.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
5203C24D2D997D2800576D4A /* iKeyMon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iKeyMon.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
5221016B2EE5E82700D04952 /* appcast.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = appcast.xml; sourceTree = "<group>"; };
|
||||||
52A9B7872EC8E7EE004DD4A2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
52A9B7872EC8E7EE004DD4A2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
52A9B7882EC8E7EE004DD4A2 /* iKeyMon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = iKeyMon.entitlements; sourceTree = "<group>"; };
|
52A9B7882EC8E7EE004DD4A2 /* iKeyMon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = iKeyMon.entitlements; sourceTree = "<group>"; };
|
||||||
52A9B8212EC8FA8A004DD4A2 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
|
52A9B8212EC8FA8A004DD4A2 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
|
||||||
@@ -76,6 +78,7 @@
|
|||||||
52A9B9712ECF751C004DD4A2 /* signing.env.example */,
|
52A9B9712ECF751C004DD4A2 /* signing.env.example */,
|
||||||
52A9BEC92ED3874F004DD4A2 /* README.md */,
|
52A9BEC92ED3874F004DD4A2 /* README.md */,
|
||||||
52A9BD122ED37E08004DD4A2 /* Frameworks */,
|
52A9BD122ED37E08004DD4A2 /* Frameworks */,
|
||||||
|
5221016C2EE5E82700D04952 /* Sparkle */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -87,6 +90,14 @@
|
|||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
5221016C2EE5E82700D04952 /* Sparkle */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
5221016B2EE5E82700D04952 /* appcast.xml */,
|
||||||
|
);
|
||||||
|
path = Sparkle;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
52A9BD122ED37E08004DD4A2 /* Frameworks */ = {
|
52A9BD122ED37E08004DD4A2 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -166,6 +177,7 @@
|
|||||||
files = (
|
files = (
|
||||||
52A9B8222EC8FA8A004DD4A2 /* CHANGELOG.md in Resources */,
|
52A9B8222EC8FA8A004DD4A2 /* CHANGELOG.md in Resources */,
|
||||||
52A9BECA2ED3874F004DD4A2 /* README.md in Resources */,
|
52A9BECA2ED3874F004DD4A2 /* README.md in Resources */,
|
||||||
|
5221016D2EE5E82700D04952 /* appcast.xml in Resources */,
|
||||||
52A9B79F2EC8E7EE004DD4A2 /* Assets.xcassets in Resources */,
|
52A9B79F2EC8E7EE004DD4A2 /* Assets.xcassets in Resources */,
|
||||||
52A9B9722ECF751C004DD4A2 /* signing.env.example in Resources */,
|
52A9B9722ECF751C004DD4A2 /* signing.env.example in Resources */,
|
||||||
);
|
);
|
||||||
@@ -310,7 +322,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = iKeyMon.entitlements;
|
CODE_SIGN_ENTITLEMENTS = iKeyMon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 79;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = Q5486ZVAFT;
|
DEVELOPMENT_TEAM = Q5486ZVAFT;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
@@ -325,7 +337,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 26.0.29;
|
MARKETING_VERSION = 26.0.38;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = net.24unix.iKeyMon;
|
PRODUCT_BUNDLE_IDENTIFIER = net.24unix.iKeyMon;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
@@ -341,7 +353,7 @@
|
|||||||
CODE_SIGN_ENTITLEMENTS = iKeyMon.entitlements;
|
CODE_SIGN_ENTITLEMENTS = iKeyMon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 79;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = Q5486ZVAFT;
|
DEVELOPMENT_TEAM = Q5486ZVAFT;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
@@ -356,7 +368,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 26.0.29;
|
MARKETING_VERSION = 26.0.38;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = net.24unix.iKeyMon;
|
PRODUCT_BUNDLE_IDENTIFIER = net.24unix.iKeyMon;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|||||||
@@ -32,8 +32,13 @@ generate_appcast() {
|
|||||||
local download_prefix=""
|
local download_prefix=""
|
||||||
if [[ -n "${SPARKLE_DOWNLOAD_BASE_TEMPLATE:-}" ]]; then
|
if [[ -n "${SPARKLE_DOWNLOAD_BASE_TEMPLATE:-}" ]]; then
|
||||||
download_prefix="${SPARKLE_DOWNLOAD_BASE_TEMPLATE//\{\{VERSION\}\}/$VERSION}"
|
download_prefix="${SPARKLE_DOWNLOAD_BASE_TEMPLATE//\{\{VERSION\}\}/$VERSION}"
|
||||||
else
|
elif [[ -n "${SPARKLE_DOWNLOAD_BASE_URL:-}" ]]; then
|
||||||
download_prefix="${SPARKLE_DOWNLOAD_BASE_URL:-}"
|
download_prefix="${SPARKLE_DOWNLOAD_BASE_URL%/}/v${VERSION}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure the version segment is present to match Gitea's /download/vX.Y.Z/ layout.
|
||||||
|
if [[ -n "$download_prefix" ]] && [[ "$download_prefix" != *"/$VERSION"* ]]; then
|
||||||
|
download_prefix="${download_prefix%/}/v${VERSION}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$generator" || -z "${SPARKLE_EDDSA_KEY_FILE:-}" || -z "$download_prefix" ]]; then
|
if [[ -z "$generator" || -z "${SPARKLE_EDDSA_KEY_FILE:-}" || -z "$download_prefix" ]]; then
|
||||||
|
|||||||
75
scripts/make_local_appcast.sh
Executable file
75
scripts/make_local_appcast.sh
Executable file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Generate a local appcast that reuses the latest Sparkle entry but bumps the
|
||||||
|
# sparkle:version so Sparkle will reinstall the same build. Useful for testing
|
||||||
|
# updates without cutting a new release.
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
INPUT="${1:-$ROOT_DIR/Sparkle/appcast.xml}"
|
||||||
|
OUTPUT="${2:-$ROOT_DIR/Sparkle/appcast-local.xml}"
|
||||||
|
|
||||||
|
python3 - "$INPUT" "$OUTPUT" <<'PY'
|
||||||
|
import sys, xml.etree.ElementTree as ET, datetime, email.utils
|
||||||
|
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
sys.exit("Usage: make_local_appcast.sh [input] [output]")
|
||||||
|
|
||||||
|
src, dst = sys.argv[1], sys.argv[2]
|
||||||
|
tree = ET.parse(src)
|
||||||
|
root = tree.getroot()
|
||||||
|
channel = root.find("channel")
|
||||||
|
items = channel.findall("item") if channel is not None else []
|
||||||
|
if not items:
|
||||||
|
sys.exit("No items found in appcast")
|
||||||
|
|
||||||
|
latest = items[0]
|
||||||
|
enc = latest.find("enclosure")
|
||||||
|
if enc is None:
|
||||||
|
sys.exit("Latest item missing enclosure")
|
||||||
|
|
||||||
|
sparkle_ns = "{http://www.andymatuschak.org/xml-namespaces/sparkle}"
|
||||||
|
|
||||||
|
def get_text(tag):
|
||||||
|
el = latest.find(tag)
|
||||||
|
return el.text if el is not None else ""
|
||||||
|
|
||||||
|
short_version = get_text(f"{sparkle_ns}shortVersionString")
|
||||||
|
version_el = latest.find(f"{sparkle_ns}version")
|
||||||
|
try:
|
||||||
|
next_build = str(int(version_el.text) + 1000 if version_el is not None else 9999)
|
||||||
|
except ValueError:
|
||||||
|
next_build = "9999"
|
||||||
|
|
||||||
|
now_rfc822 = email.utils.format_datetime(datetime.datetime.now(datetime.timezone.utc))
|
||||||
|
|
||||||
|
new_item = ET.Element("item")
|
||||||
|
ET.SubElement(new_item, "title").text = f"{short_version} (reinstall)"
|
||||||
|
ET.SubElement(new_item, "pubDate").text = now_rfc822
|
||||||
|
sv = ET.SubElement(new_item, f"{sparkle_ns}shortVersionString")
|
||||||
|
sv.text = short_version
|
||||||
|
bv = ET.SubElement(new_item, f"{sparkle_ns}version")
|
||||||
|
bv.text = next_build
|
||||||
|
min_os = latest.find(f"{sparkle_ns}minimumSystemVersion")
|
||||||
|
if min_os is not None and min_os.text:
|
||||||
|
ET.SubElement(new_item, f"{sparkle_ns}minimumSystemVersion").text = min_os.text
|
||||||
|
new_enc = ET.SubElement(new_item, "enclosure")
|
||||||
|
for attr in ("url", "length", "type", f"{sparkle_ns}edSignature"):
|
||||||
|
if attr in enc.attrib:
|
||||||
|
new_enc.set(attr, enc.attrib[attr])
|
||||||
|
|
||||||
|
new_channel = ET.Element("channel")
|
||||||
|
title = channel.find("title")
|
||||||
|
ET.SubElement(new_channel, "title").text = title.text if title is not None else "Local"
|
||||||
|
new_channel.append(new_item)
|
||||||
|
|
||||||
|
new_root = ET.Element("rss", {
|
||||||
|
"version": "2.0",
|
||||||
|
"xmlns:sparkle": "http://www.andymatuschak.org/xml-namespaces/sparkle"
|
||||||
|
})
|
||||||
|
new_root.append(new_channel)
|
||||||
|
|
||||||
|
ET.indent(new_root, space=" ")
|
||||||
|
ET.ElementTree(new_root).write(dst, encoding="utf-8", xml_declaration=True)
|
||||||
|
print(f"✅ wrote {dst}")
|
||||||
|
PY
|
||||||
25
scripts/serve_local_appcast.sh
Executable file
25
scripts/serve_local_appcast.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Generate a local appcast and serve it over HTTP for Sparkle testing without
|
||||||
|
# publishing a new release. Sparkle disallows file:// feeds, so we use
|
||||||
|
# http://localhost:${PORT}/appcast-local.xml.
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
PORT="${PORT:-8000}"
|
||||||
|
WORKDIR="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$WORKDIR"' EXIT
|
||||||
|
|
||||||
|
"$ROOT_DIR/scripts/make_local_appcast.sh" "${1:-$ROOT_DIR/Sparkle/appcast.xml}" "$WORKDIR/appcast-local.xml"
|
||||||
|
|
||||||
|
echo "🍏 Serving local appcast on http://127.0.0.1:${PORT}/appcast-local.xml"
|
||||||
|
echo "Set SUFeedURL to that URL, then launch iKeyMon and check for updates."
|
||||||
|
echo
|
||||||
|
echo "To set it:"
|
||||||
|
echo " defaults write net.24unix.iKeyMon SUFeedURL \"http://127.0.0.1:${PORT}/appcast-local.xml\""
|
||||||
|
echo " killall iKeyMon 2>/dev/null; open /Applications/iKeyMon.app"
|
||||||
|
echo
|
||||||
|
echo "Press Ctrl+C to stop."
|
||||||
|
|
||||||
|
cd "$WORKDIR"
|
||||||
|
python3 -m http.server "$PORT"
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"marketing_version": "26.0.29"
|
"marketing_version": "26.0.38"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user