1

I'm having problems at work where we are trying to split our legacy codebase into smaller composer projects to decouple the code and refactor in a controlled way.

We host our code on bitbucket and have a satis repo with "require-all": true and all of our repos listed. This has been working really well.

The problem we are having is when we come to tag new versions of our projects, we have to update all of the other projects which depend on it to point to the exact version number we just tagged. We started to use wildcards to try and alleviate this pain and then just setting a specific version number in our 'core' application, however, we get errors like could not be found in any version even though if we change back to have all the version numbers statically set the same, it works fine.

Project A composer.json

...
"require": {
    "doctrine/dbal": "2.4"
}
...

Project B composer.json

...
"require": {
    "acmeco/project_a": "1.0.*"
},
...

Project C composer.json

...
"minimum-stability": "stable",
"require": {
    "acmeco/project_a": "1.0.4"
    "acmeco/project_b": "1.0.9"
}
...

When running composer update we get the following:

Your requirements could not be resolved to an installable set of packages.

Problem 1
  - The requested package acmeco/project_a could not be found in any version, there may be a typo in the package name.
Problem 2
  - acmeco/project_b 1.0.9 requires acmeco/project_a 1.0.4 -> no matching package found.
  - acmeco/project_b 1.0.9 requires acmeco/project_a 1.0.* -> no matching package found.
  - Installation request for acmeco/project_b 1.0.9 -> satisfiable by acmeco/project_b[1.0.9].

If I change Project C's composer.json to use 1.0.* or Project B's composer to use 1.0.4, all is right with the world.

Maybe I'm not using composer as intended but I'd have thought it would see that Project B just wants 1.0.* of project_a and Project C wants the specific 1.0.4 so it should just go ahead and install project_a 1.0.4 because everyone is happy with that.

Any help/suggestions is much appreciated.

4

1 回答 1

2

首先:坚持语义化版本控制。始终评估新版本是否仅修复某些内容、添加新功能或破坏向后兼容性,并相应地标记它。如果您无意中没有正确地增加版本,您应该将其视为错误,恢复更改并将其作为错误修复发布。然后,您可以使用更高级别的版本增量发布更改。

如果您获得正确的语义版本,则可以更改为使用波浪号运算符来指定版本。我是它们的忠实粉丝,它们在语义版本中表现得特别好。

这意味着在您的项目 C 中,您将

"require": {
    "acmeco/project_a": "~1.0",
    "acmeco/project_b": "~1.0"
}

在项目 B 中还有:

"require": {
    "acmeco/project_a": "~1.0"
}

在项目 A 中(取决于“doctrine/dbal”是否承诺实现语义版本 - 如果不是:)2.4.*

"require": {
    "doctrine/dbal": "~2.4"
}

然后你应该解释为什么项目C直接依赖于项目A。它完全有可能,但如果它有它,因为项目C中的代码使用项目A的类,那么项目B也应该受到质疑。但是,项目 C 更可能不应该直接依赖包 A,而唯一的依赖关系在包 B 中。

但另一方面,通过允许每个包都需要任何承诺兼容但可能包含错误修复和新功能的版本,您就可以为 Composer 提供所需的松弛度来获得正确的版本要求。

为了更好地可视化版本依赖关系,我强烈建议您使用graph-composer。这将揭示软件包中包含哪些版本要求。

您是否有理由认为有必要在包 C 中查明确切的版本?Composer 已经记录了您在更新时获取的确切版本,并且在安装时将始终安装该确切版本(您必须提交composer.lock文件)。

只需要更改composer.json文件中的版本要求:如果您知道您需要一项仅适用于包的新(兼容或不兼容)版本的新功能,则应明确更改版本要求。对于不兼容的更改,这是必需的 - 否则您将无法获得更新。对于兼容的更改,您仍然可以更改它,即使您会自动获得较新的版本,以防万一另一个包以后可能会强制降级。

于 2014-08-13T21:09:31.913 回答