1
0
Fork 0

Merge pull request #9902 from Seldaek/cyclic-deps

Detect and output a better hint for cyclic dependencies
pull/9925/head
Nils Adermann 2021-05-25 22:58:50 +02:00 committed by GitHub
commit 21c70c2606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 19 deletions

View File

@ -47,32 +47,39 @@ This is a list of common pitfalls on using Composer, and how to avoid them.
In this case add the `--with-dependencies` argument **or** add all dependencies which
need an update to the command.
## Package not found on travis-ci.org
## Dependencies on the root package
1. Check the ["Package not found"](#package-not-found) item above.
When your root package depends on a package which ends up depending (directly or
indirectly) back on the root package itself, issues can occur in two cases:
2. If the package tested is a dependency of one of its dependencies (cyclic
dependency), the problem might be that Composer is not able to detect the version
of the package properly. If it is a git clone it is generally alright and Composer
will detect the version of the current branch, but travis does shallow clones so
that process can fail when testing pull requests and feature branches in general.
1. During development, if you are on a branch like `dev-main` and the branch has no
[branch-alias](aliases.md#branch-alias) defined, and the dependency on the root package
requires version `^2.0` for example, the `dev-main` version will not satisfy it.
The best solution here is to make sure you first define a branch alias.
2. In CI (Continuous Integration) runs, the problem might be that Composer is not able
to detect the version of the root package properly. If it is a git clone it is
generally alright and Composer will detect the version of the current branch,
but some CIs do shallow clones so that process can fail when testing pull requests
and feature branches. In these cases the branch alias may then not be recognized.
The best solution is to define the version you are on via an environment variable
called COMPOSER_ROOT_VERSION. You set it to `dev-master` for example to define
the root package's version as `dev-master`.
Use: `before_script: COMPOSER_ROOT_VERSION=dev-master composer install` to export
the variable for the call to composer.
called COMPOSER_ROOT_VERSION. You set it to `dev-main` for example to define
the root package's version as `dev-main`.
Use for example: `COMPOSER_ROOT_VERSION=dev-main composer install` to export
the variable only for the call to composer, or you can define it globally in the
CI env vars.
## Package not found in a Jenkins-build
1. Check the ["Package not found"](#package-not-found) item above.
2. Reason for failing is similar to the problem which can occur on travis-ci.org: The
git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As
a result, Composer is not able to identify the version of the current checked out branch
and may not be able to resolve a cyclic dependency. To solve this problem, you can use
the "Additional Behaviours" -> "Check out to specific local branch" in your Git-settings
for your Jenkins-job, where your "local branch" shall be the same branch as you are
checking out. Using this, the checkout will not be in detached state any more and cyclic
dependency is recognized correctly.
2. The git-clone / checkout within Jenkins leaves the branch in a "detached HEAD"-state. As
a result, Composer may not able to identify the version of the current checked out branch
and may not be able to resolve a [dependency on the root package](#dependencies-on-the-root-package).
To solve this problem, you can use the "Additional Behaviours" -> "Check out to specific local
branch" in your Git-settings for your Jenkins-job, where your "local branch" shall be the same
branch as you are checking out. Using this, the checkout will not be in detached state any more
and the dependency on the root package should become satisfied.
## I have a dependency which contains a "repositories" definition in its composer.json, but it seems to be ignored.

View File

@ -14,6 +14,7 @@ namespace Composer\DependencyResolver;
use Composer\Package\CompletePackageInterface;
use Composer\Package\AliasPackage;
use Composer\Package\RootPackageInterface;
use Composer\Repository\RepositorySet;
use Composer\Repository\LockArrayRepository;
use Composer\Semver\Constraint\Constraint;
@ -428,6 +429,17 @@ class Problem
}
}
if ($higherRepoPackages) {
$topPackage = reset($higherRepoPackages);
if ($topPackage instanceof RootPackageInterface) {
$singular = count($nextRepoPackages) === 1;
return array(
"- Root composer.json requires $packageName".self::constraintToText($constraint).', it is ',
'satisfiable by '.self::getPackageList($nextRepoPackages, $isVerbose).' from '.$nextRepo->getRepoName().' but '.$topPackage->getPrettyName().' is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.'
);
}
}
if ($nextRepo instanceof LockArrayRepository) {
$singular = count($higherRepoPackages) === 1;

View File

@ -0,0 +1,45 @@
--TEST--
Circular dependencies errors uses helpful message
--COMPOSER--
{
"name": "root/pkg",
"version": "dev-master",
"require": {
"requires/root": "1.0.0"
},
"repositories": [
{
"type": "package",
"package": [
{
"name": "requires/root",
"version": "1.0.0",
"source": { "reference": "some.branch", "type": "git", "url": "" },
"require": {
"root/pkg": "^1.0"
}
},
{
"name": "root/pkg",
"version": "1.0.0"
}
]
}
]
}
--RUN--
update -v
--EXPECT-EXIT-CODE--
2
--EXPECT-OUTPUT--
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires requires/root 1.0.0 -> satisfiable by requires/root[1.0.0].
- requires/root 1.0.0 requires root/pkg ^1.0 -> satisfiable by root/pkg[1.0.0] from package repo (defining 2 packages) but root/pkg is the root package and cannot be modified. See https://getcomposer.org/dep-on-root for details and assistance.
--EXPECT--