我正试图找到一种适当的方法来强制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/package
的version
命令1:
$ composer require sample/package
从packagegist获取包(版本1.0.0
,提交aaaaaa
)。
命令2:
$ composer require sample/package:@dev
包从本地版本符号链接到供应商目录(版本1.0.0
,提交bbbbbb
,符号链接)。
问题是:
- 为什么命令1从packagegist下载包,而不考虑
minimum-stability
选项?版本约束@dev
允许您强制执行不同的稳定性,但在项目配置中已经降到了dev
- 在任何情况下,命令2都会创建到本地包的符号链接吗
- 有没有比命令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提供的非常有用的信息不起作用,也许您正处于这种情况:
- 您正在使用特定的分支(例如,
dev-master
) - 您正在使用的分支来自您的远程存储库
- 您正在尝试符号链接同一个分支,但这次使用的是路径(因此,在
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
),然后要求使用该版本,从而向您显示哪些依赖项无法实现(然后您可以更改它)。