强制composer符号链接本地包



我正试图找到一种适当的方法来强制composersymlink本地包。

我知道有一个问题如何强制Composer下载本地包?但它不能回答我的问题。我需要确保它按预期工作,因为我将在CI工作流中使用它。

拥有类似于项目的composer.json:

{
"name": "Some project",
"type": "project",
"minimum-stability": "dev",
"prefer-stable": true,
"repositories": [{
"type": "path", 
"url": "packages/*/*"
}]
}

And package的composer.json(packages/sample/package):

{
"name": "Sample package",
"version": "1.0.0"
}

让我们假设:

  • sample/package:1.0.0在packagist中发布(提交aaaaaa)-带有未修改的composer.json
  • 提交bbbbbb时本地签出sample/package
  • 无法在本地修改sample/packageversion

命令1:

$ composer require sample/package

从packagegist获取包(版本1.0.0,提交aaaaaa)。

命令2:

$ composer require sample/package:@dev

包从本地版本符号链接到供应商目录(版本1.0.0,提交bbbbbb,符号链接)。

问题是:

  1. 为什么命令1从packagegist下载包,而不考虑minimum-stability选项?版本约束@dev允许您强制执行不同的稳定性,但在项目配置中已经降到了dev
  2. 在任何情况下,命令2都会创建到本地包的符号链接吗
  3. 有没有比命令2更好的方法来确保本地包被符号链接

为什么Command 1从packagegist下载软件包而不考虑最低稳定性选项?版本约束@dev允许您强制执行不同的稳定性,但它已经取决于项目配置的dev

我最好的猜测是,当composer require sample/package中没有提供版本约束时,Composer仍然会尝试找到一个稳定的版本来安装,因为"prefer-stable": true。当您将此选项设置为false(或显式为包提供@dev版本约束)时,您应该看到Composer使用最新的可用版本(提交bbbbbb时为dev-master)。

命令2会在任何情况下都创建到本地包的符号链接吗

并非所有情况都如此。您可以使用"symlink": true选项强制Composer始终符号链接包。

发件人https://getcomposer.org/doc/05-repositories.md#path:

如果可能,本地包将被符号链接,在这种情况下,控制台中的输出将从../../packages/my-package读取符号链接。如果无法进行符号链接,则将复制包。在这种情况下,控制台将从../../packages/my-package输出Mirrored。

您可以强制使用带有"symlink": true的符号链接或带有"symlink": false选项的镜像,而不是默认的回退策略。当从单片存储库部署或生成包时,强制镜像可能很有用。

有比命令2更好的方法来确保本地包被符号链接吗

您可能应该避免从composer.json中删除"prefer-stable": true,因为这会影响所有依赖关系。

我建议确保sample/package明确要求@dev版本,并为本地存储库设置"symlink": true。这将导致类似于:

{
"name": "Some project",
"type": "project",
"minimum-stability": "dev",
"prefer-stable": true,
"repositories": [{
"type": "path", 
"url": "packages/*/*",
"symlink": true
}],
"require": {
"sample/package": "@dev"
}
}

这可能不起作用的另一个原因是repository中有多个条目。Composer将使用它首先在中找到包的存储库定义。

在我们的案例中,我们使用了一个自定义的Satis存储库。在satis repo之后定义本地包时,它永远不会进行符号链接,而是始终使用satis版本。当首先定义本地包时,它确实有效。

工作示例:

"repositories": {
"our/local-package": {
"type": "path",
"url": "../../some-local-package",
"options": {
"symlink": true
}
},
"satis": {
"type": "composer",
"url": "http://our.satis.url/"
}
}

然后呼叫composer require our/local-package:@dev

如果@Maciek Lewkowicz提供的非常有用的信息不起作用,也许您正处于这种情况:

  1. 您正在使用特定的分支(例如,dev-master)
  2. 您正在使用的分支来自您的远程存储库
  3. 您正在尝试符号链接同一个分支,但这次使用的是路径(因此,在composer.json中更改的唯一内容是包的源,并在composer.json文件的repositories密钥中设置repo)

在这种情况下,简单的composer update将不起作用:Composer将不会拦截更改:因为Composer与您将存储库从远程更改为本地路径无关。它只检查分支是否相同,因此根本不更新。

因此,在这种情况下,什么都不起作用:使用symlink: force不起作用,也不起作用来更改有关源的首选项等等

唯一有效的方法是更改分支。

例如,您的composer.json将是这样的:

{
...
"require": {
...
-       "your/package": "dev-master",
+       "your/package": "dev-dev",
...
},
...
"repositories": [
{
"type": "path",
"url": "/Path/To/Your/Local/package"
}
]
}

这里dev-dev是一个名为dev的新分支:将分支从dev-master更改为dev-dev将迫使Composer再次下载包,因为所需的分支不再是dev-master

在再次下载包时,Composer还将检查新的源是否现在是本地路径,因此它将符号链接文件夹。

还要注意,如果更改分支名称,composer install也将不起作用。

您必须使用composer update

为了对这里已经很好的答案进行一点扩展,我遇到了同样的问题,但解决方案略有不同:

当您的本地包和远程repo中有相同的"版本"可用(分支、标记、哈希)时,如果composer无法解析本地包的依赖项,它只会静默地从远程repo拖动版本,只要这些依赖项可以解析。

为了调试它,您可以向本地包package.json的"版本"属性添加一些奇怪的版本(例如100),然后要求使用该版本,从而向您显示哪些依赖项无法实现(然后您可以更改它)。

相关内容

  • 没有找到相关文章

最新更新