diff --git a/USAGE.md b/USAGE.md index 51d58cf..b793d85 100644 --- a/USAGE.md +++ b/USAGE.md @@ -45,7 +45,8 @@ ykanban ``` - Exactly one argument is accepted. A relative path is resolved against the - current working directory, so `ykanban .` opens the current folder. + current working directory, so `ykanban .` opens the current folder (but see + [macOS](#macos) when starting through `open`). - YKanBan looks for `.ykanban` **only in `` itself**; it does not search parent folders the way Git does. - There are no command-line options. An argument starting with `-` is never @@ -57,7 +58,7 @@ instead: | Page | When | |---|---| -| Invalid arguments | No argument, more than one argument, an empty argument, or an argument starting with `-` (including `--help`). Shows the usage line. | +| Invalid arguments | No argument, more than one argument, an empty or whitespace-only argument, an argument starting with `-` (including `--help`), or a path the operating system cannot represent (for example one containing a NUL character). Shows the usage line. | | Folder not found | `` does not exist or is not a folder. | | No workspace here | `` exists but has no `.ykanban`. The **Initialize workspace** button creates one, with the columns To Do / In Progress / Done (named in the current interface language). | | Workspace locked | Another YKanBan window already has this workspace open. Close that window first. | @@ -80,12 +81,17 @@ Double-clicking `YKanBan.app` starts it without a path, so it only shows the Launch Services or by running the executable inside the bundle: ```sh -open -a YKanBan --args /path/to/project +open -n -a YKanBan --args /path/to/project /Applications/YKanBan.app/Contents/MacOS/YKanBan /path/to/project ``` -`open -a YKanBan` finds the app once it is in `/Applications` (or another -folder Launch Services knows about). +- Keep `-n`: without it, `open` only brings an already running YKanBan to + the front and drops the path, instead of starting another window. +- Give `open` an **absolute** path. An app started by `open` runs in `/`, so + `open -n -a YKanBan --args .` opens `/`, not the current folder. Running the + executable inside the bundle resolves relative paths normally. +- `open -a YKanBan` finds the app once it is in `/Applications` (or another + folder Launch Services knows about). ## Workspaces, Git and backups diff --git a/docs/ACCEPTANCE.md b/docs/ACCEPTANCE.md index 3721c8e..33ed957 100644 --- a/docs/ACCEPTANCE.md +++ b/docs/ACCEPTANCE.md @@ -46,7 +46,7 @@ ## B. 启动与错误页(M4 / M4R) -- [ ] 无参数、两个参数、`--help`、`-x`、空字符串参数 → 参数错误页,显示 `Usage: ykanban ` +- [ ] 无参数、两个参数、`--help`、`-x`、空字符串参数、纯空格参数 → 参数错误页,显示 `Usage: ykanban ` - [ ] 不存在的路径、指向文件的路径 → 目录不存在页 - [ ] 相对路径(如 `ykanban .`)按当前目录解析 - [ ] 无 `.ykanban` 的文件夹 → 未初始化页;点"初始化"后进入看板,预置三列 @@ -98,5 +98,5 @@ - [ ] 产物:`YKanBan-<版本>-win-x64.zip`、`-linux-x64.tar.gz`、`-osx-x64.tar.gz`、`-osx-arm64.tar.gz` - [ ] Windows:解压后 `YKanBan.exe ` 可直接运行(自包含,无需安装 .NET) - [ ] Linux:解压后 `./YKanBan ` 可运行(可执行位保留) -- [ ] macOS:解除隔离后 `open -a YKanBan --args ` 与直接运行包内可执行文件均可用;双击 `.app` 只显示参数错误页 +- [ ] macOS:解除隔离后 `open -n -a YKanBan --args <绝对路径>` 与直接运行包内可执行文件均可用;双击 `.app` 只显示参数错误页 - [ ] 故意让某平台测试失败 → 该 RID 无产物,其余 RID 不受影响 diff --git a/docs/PLAN.md b/docs/PLAN.md index 303e371..3fc195a 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -122,7 +122,7 @@ card_tags: (card_id, tag_id) 复合主键,双向 ON DELETE CASCADE - 恰好一个位置参数为合法;相对路径以进程当前工作目录解析为绝对路径 - 无参数、多于一个参数、或参数以 `-` 开头(含 `--help` 等任何选项形式)→ **参数错误页** - 路径不存在或存在但不是目录 → 目录不存在页 -- macOS 双击 `.app` 时无参数,只会显示参数错误页——已接受(纯命令行定位);USAGE.md 说明 macOS 启动方式(`open -a YKanBan --args ` 或直接运行包内可执行文件) +- macOS 双击 `.app` 时无参数,只会显示参数错误页——已接受(纯命令行定位);USAGE.md 说明 macOS 启动方式:`open -n -a YKanBan --args <绝对路径>` 或直接运行包内可执行文件(`-n` 保证已有实例运行时仍另起实例;经 `open` 启动时当前目录为 `/`,故须绝对路径) - 窗口标题:`工作区名 - YKanBan`;无有效工作区(错误页状态)时仅 `YKanBan` ### 4.2 连接管理 @@ -398,4 +398,4 @@ phrase := '"' 任意文本 '"' (内部支持转义:\" → 字面引号, 2. 备份/迁移必须同时复制 `ykanban.db`、`ykanban.db-wal`、`ykanban.db-shm` 三个文件;不支持将工作区放在网络共享(SMB/NFS)上 3. 搜索语法全文(文法、语义、`word` 字符集、转义规则、保留字、大小写折叠、严格校验与非法表达式清单、错误对话框行为,见 §6) 4. 命令行启动规则(`ykanban `;参数规则与各错误页,见 §4.1) -5. macOS 启动方式(`open -a YKanBan --args ` 或直接运行包内可执行文件;双击 `.app` 只会显示参数错误页) +5. macOS 启动方式(`open -n -a YKanBan --args <绝对路径>` 或直接运行包内可执行文件;`-n` 保证另起实例,`open` 启动时当前目录为 `/` 故须绝对路径;双击 `.app` 只会显示参数错误页) diff --git a/packaging/package.sh b/packaging/package.sh index 03fbfbf..627befb 100755 --- a/packaging/package.sh +++ b/packaging/package.sh @@ -5,7 +5,7 @@ # # win-x64 -> YKanBan--win-x64.zip (folder YKanBan--win-x64/) # linux-x64 -> YKanBan--linux-x64.tar.gz (folder YKanBan--linux-x64/) -# osx-* -> YKanBan--.tar.gz (YKanBan.app bundle, ad-hoc signed when codesign exists) +# osx-* -> YKanBan--.tar.gz (YKanBan.app bundle, ad-hoc signed when possible) # # tar.gz keeps the executable bit, which a plain zip artifact upload would lose. set -euo pipefail @@ -28,9 +28,15 @@ trap 'rm -rf "$staging"' EXIT case "$rid" in win-*) cp -R "$publish_dir" "$staging/$name" - # Compress-Archive is available on every Windows host, unlike zip. - powershell -NoProfile -Command \ - "Compress-Archive -Path '$(cygpath -w "$staging/$name" 2>/dev/null || echo "$staging/$name")' -DestinationPath '$(cygpath -w "$output_dir/$name.zip" 2>/dev/null || echo "$output_dir/$name.zip")' -Force" + rm -f "$output_dir/$name.zip" + # 7-Zip ships on the Windows runners and writes '/' entry separators; + # Windows PowerShell 5.1's Compress-Archive writes '\', which breaks + # extraction outside Windows. + if ! command -v 7z > /dev/null 2>&1; then + echo "7z not found" >&2 + exit 1 + fi + (cd "$staging" && 7z a -tzip -bso0 -bsp0 "$output_dir/$name.zip" "$name") ;; linux-*) cp -R "$publish_dir" "$staging/$name" @@ -44,8 +50,12 @@ case "$rid" in chmod +x "$app/Contents/MacOS/YKanBan" sed "s/@VERSION@/${version}/g" "$script_dir/macos/Info.plist" > "$app/Contents/Info.plist" if command -v codesign > /dev/null 2>&1; then - # Ad-hoc signature: unsigned arm64 code does not run at all. - codesign --force --deep --sign - "$app" + # Ad-hoc signature for the bundle. Not fatal: the SDK already ad-hoc + # signs the apphost, which is all arm64 needs to run, and --deep may + # trip over the non-Mach-O files in Contents/MacOS. + if ! codesign --force --deep --sign - "$app"; then + echo "warning: ad-hoc signing of YKanBan.app failed; packing it unsigned" >&2 + fi fi tar -C "$staging" -czf "$output_dir/$name.tar.gz" YKanBan.app ;;