Skip to content

上流のアーカイブ構造変更に追従できず、失敗も検知できない場合がある #2425

Description

@hal-shu-sato

背景

open な bug issue を分類する過程(#2379)で、#2123#2085 が同じ根を持つと分かった。どちらも「上流がアーカイブの構造を変えたが apm-data の定義が古いまま」だが、症状が正反対で、そこに apm 側の課題が 2 つ見える。

前提として、downloadURLs は多くのパッケージで releases/latest を指している。つまりユーザーは常に上流の最新アーカイブを取得する一方、files / archivePath は apm-data を更新するまで古い構造を記述したままになる。この乖離は構造的に避けられない。

課題 1: archivePath がリテラルで、バージョン入りの階層に追従できない

src/shared/install.ts のコピー元はこう決まる。

file.archivePath
  ? resolveInside(unzippedPath, file.archivePath, path.basename(file.filename))
  : path.join(unzippedPath, path.basename(file.filename))

archivePath はリテラルで、グロブは効かない。

#2123(x264guiEx)では、上流のアーカイブが x264guiEx_3.31v3/plugins/... のようにバージョン名のルート階層を持つ形になっていた。apm-data は archivePath: "plugins" なので届かない。

問題は、フォルダ名にバージョンが入るため固定値では原理的に追従できないこと。apm-data の値を直しても次のリリースでまた壊れる。

考えられる方向:

  1. archivePath にグロブを許す(matcher は既に依存にある)
  2. 展開結果が単一のルートディレクトリだけの場合、それを自動的に剥がす
  3. 何もしない — apm-data 側で毎リリース追従する(現実的でない)

なお #2123失敗が表に出るplugins/x264guiEx.auo 等は通常ファイルなので verifyFilesByCount に引っかかり、報告者も「エラーが発生しました」と見えている。挙動としては正しい。

課題 2: isUninstallOnly のファイルが検証から除外されている

export function verifyFilesByCount(installationPath: string, files: Files) {
  for (const file of files) {
    if (!file.isUninstallOnly && !file.isObsolete) {   // ← 除外

#2085(アルティメットプラグイン)の plugins/ultimateisDirectory かつ isUninstallOnly で定義されている。このためコピーに失敗しても検証対象に入らず、インストールは成功扱いになる。報告者の環境で module/ が丸ごと無いのにエラーが出なかったのはこのため。

isUninstallOnly の実装は「アンインストール時にだけ消す」ではなく、コピー時も

if (existsSync(filePath[0]) && !existsSync(filePath[1])) filesToCopy.push(filePath);

つまり「コピー元にあり、コピー先に無ければ入れる」。既に存在する場合は更新されないので、上流が新しいモジュールを追加しても届かない。ディレクトリ丸ごとを isUninstallOnly にすると、この性質が subtree 全体に効く。

検証から外れているぶん、失敗が誰にも見えない点が課題。

先に apm-data の更新が要る(2026-08-23 追記)

この issue の設計判断に入る前に、apm-data の更新が必要であることが分かった。GitHub 由来のパッケージ 79 件について、apm-data の latestVersion と上流の最新リリースを突き合わせた結果:

  • 一致: 55 件
  • 不一致: 21 件
  • リリース情報を取得できず: 3 件

不一致のうち、この issue に直接関わるもの:

パッケージ apm-data 上流
rigaya/x264guiEx(#2123) 3.31 4.12
hebiiro/UltimatePlugin(#2085) r38 r117
rigaya/NVEnc 7.73 9.32
rigaya/QSVEnc 7.72 8.27
rigaya/svtAV1guiEx 1.26 2.13
rigaya/x265guiEx 4.21 5.10
rigaya/VCEEnc 8.23 9.13

#2123 の x264guiEx はデータが 3.31、上流は 4.12。 報告当時のアーカイブ構造(x264guiEx_3.31v3/)を前提に設計を決めても、現在の 4.12 では構造が変わっている可能性がある。同様に #2085 も r38 と r117 で開きが大きい。

したがって次の順序になる。

  1. apm-data を更新する
  2. 更新後も x264guiExのインストールに失敗する #2123 / アルティメットプラグインをうまく導入できない #2085 が再現するか確かめる
  3. 再現するなら、そのときの実際のアーカイブ構造をもとに課題 1 の方向を決める

課題 2(検証の穴)はデータの新旧に依存しないため、独立して進められる。ただし単純に isUninstallOnly を検証対象へ含めると「アーカイブに無いのが正常」なケースまで失敗扱いになるため、切り分けが要る。

調査の副産物

同じ突き合わせで、データ側の別の異常も見つかった。

  • latestVersion最新 という文字列HolyWu/LSMASHWorks / MrOjii/LSMASHWorks / VFRmaniac/LSMASHWorks の 3 件。バージョン比較が機能しないはず
  • oov/PSDToolKit — data が 0.2beta56 で上流が 0.1.3。データのほうが新しく見えるので、上流のリリースタグとは別の場所で配布している可能性

いずれも apm-data 側の話なので、この issue では扱わない。

確認した事実

  • matcher は既に dependencies にある(グロブ対応の追加コストは低い)
  • apm-data 現況: rigaya/x264guiExarchivePath: "plugins"hebiiro/UltimatePluginplugins/ultimateisDirectory + isUninstallOnly

スコープ

apm-data 側のデータ更新(#1930 / #2042 / #2085 / #2123)とは別の、apm 本体の課題としてここに切り出す。データを直しても課題 1 は再発しうるし、課題 2 は表面化しないままになるため。


調査と文面の作成に Claude Code を使用しています。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions