Use PHP composer to clone git repo
Asked Answered
M

9

142

I'm trying to use composer to automatically clone a git repository from github that isn't in packagist but it's not working and I can't figure out what am I doing wrong.

I think I have to include it among "repositories" like so:

"repositories": [
    {
        "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
        "type": "git"
    }
],

and then probably list it in "require" section. It should be similar to this example but it doesn't work. It just gives this error:

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

Have anyone tried to do something like this already?

Mantua answered 18/10, 2012 at 11:56 Comment(0)
S
138

At the time of writing in 2013, this was one way to do it. Composer has added support for better ways: See @igorw 's answer

DO YOU HAVE A REPOSITORY?

Git, Mercurial and SVN is supported by Composer.

DO YOU HAVE WRITE ACCESS TO THE REPOSITORY?

Yes?

DOES THE REPOSITORY HAVE A composer.json FILE

If you have a repository you can write to: Add a composer.json file, or fix the existing one, and DON'T use the solution below.

Go to @igorw 's answer

ONLY USE THIS IF YOU DON'T HAVE A REPOSITORY
OR IF THE REPOSITORY DOES NOT HAVE A composer.json AND YOU CANNOT ADD IT

This will override everything that Composer may be able to read from the original repository's composer.json, including the dependencies of the package and the autoloading.

Using the package type will transfer the burden of correctly defining everything onto you. The easier way is to have a composer.json file in the repository, and just use it.

This solution really only is for the rare cases where you have an abandoned ZIP download that you cannot alter, or a repository you can only read, but it isn't maintained anymore.

"repositories": [
    {
        "type":"package",
        "package": {
          "name": "l3pp4rd/doctrine-extensions",
          "version":"master",
          "source": {
              "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
              "type": "git",
              "reference":"master"
            }
        }
    }
],
"require": {
    "l3pp4rd/doctrine-extensions": "master"
}
Solemn answered 18/10, 2012 at 11:56 Comment(13)
Replacing the VCS repository with a package repository is a bad idea. The target repo already has a composer.json, so use a vcs repo. Your example also breaks autoloading and ignores the branch-alias.Heber
@Heber can you please link to that information so that I and other can understand the difference? Thanks.Solemn
As explained on the repositories page a package repo must include all information. If you don't add the autoload field, it will not be included. Basically you need to copy-paste all info from composer.json to the repo definition. The VCS repo fetches that info from VCS directly. The benefits of branch-alias are explained in the aliases doc and a blog post I wrote.Heber
you should the version instead of 'master' linkDispart
Why is this still being upvoted? The composer docs even explicitly state that package repos should be avoided. Please, stop encouraging bad practices.Heber
What do you recommend I change it to then ?Solemn
The priority is as follows: packagist, vcs, package. Package repositories are a last resort.Heber
@Heber I made this a community wiki so you can put the best practice in here and bad practices wont be encouraged.Solemn
I would like to point out that I found this post and its comments valuable because it highlights a bad practice I easily could have stumbled into.Hypochondrium
Thanks to the package feature i don't have to force needless complexity on other repos. master#commit should emulate submodules pretty well. Version numbers can be hacked.Medullated
I'm looking to this solution to store hacked code. We often depend upon a package that is no longer maintained. There simply isn't another package out there that's as good as this one - but we've had to modify it a few times to make it do everything the way we want. If not for a this solution, what the best practice?Bethanie
Good answer for the backtrack, usually if the library does not have a composer.json file as you mention , it ends up with the error 'No valid composer.json was found in any branch or tag'Tarter
Man Your comment is valid till the last day on earth simply because sometimes there is old packages that have issues and no longer gets updates from it's developer so as a developer i just download the code and fix the issues then push it to git repo and pull it when needed that saves me alot of time instead of fixing the package issues every timeUralian
H
162

That package in fact is available through packagist. You don't need a custom repository definition in this case. Just make sure you add a require (which is always needed) with a matching version constraint.

In general, if a package is available on packagist, do not add a VCS repo. It will just slow things down.


For packages that are not available via packagist, use a VCS (or git) repository, as shown in your question. When you do, make sure that:

  • The "repositories" field is specified in the root composer.json (it's a root-only field, repository definitions from required packages are ignored)
  • The repositories definition points to a valid VCS repo
  • If the type is "git" instead of "vcs" (as in your question), make sure it is in fact a git repo
  • You have a require for the package in question
  • The constraint in the require matches the versions provided by the VCS repo. You can use composer show <packagename> to find the available versions. In this case ~2.3 would be a good option.
  • The name in the require matches the name in the remote composer.json. In this case, it is gedmo/doctrine-extensions.

Here is a sample composer.json that installs the same package via a VCS repo:

{
    "repositories": [
        {
            "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
            "type": "git"
        }
    ],
    "require": {
        "gedmo/doctrine-extensions": "~2.3"
    }
}

The VCS repo docs explain all of this quite well.


If there is a git (or other VCS) repository with a composer.json available, do not use a "package" repo. Package repos require you to provide all of the metadata in the definition and will completely ignore any composer.json present in the provided dist and source. They also have additional limitations, such as not allowing for proper updates in most cases.

Avoid package repos (see also the docs).

Heber answered 18/10, 2012 at 15:13 Comment(11)
Ouu, thanks! I didn't find it because I thought it'll be called after the git repo DoctrineExtensions.Mantua
Always look at the name given in composer.json.Heber
Thanks, next time, I'll be smarter :).Mantua
-1 Why is this marked as the correct answer? It sure did solve the OP's problem but Clarence and Mike Graf gave answers to the more general problem behind it. It's highly unlikely that anybody searching for a way to include non-packagist projects would want to include the DoctrineExtensions.Unskillful
@Unskillful My answer does in fact also explain the general general problem, which is that the require field must be specified.Heber
The VCS repo docs explain all of this quite well. ... what?Menell
ps: it should add a tag for new code, otherwise, it still use previouse code.Ferdelance
This was the answer I was looking for. The others were confusing with chains of general logic which I only found confusing. YMMVHaircloth
Why do we have once "l3pp4rd/DoctrineExtensions" and once "gedmo/doctrine-extensions"?Nagey
Don't know if just a temporary "instability", but I had to use the git repo without the .git suffixTarter
This does not seem to be a complete replacement, it might work for your own usage, but due to recursive repository specifications, and even if you re-specify the repository directly, it won't be capable to find the library when you specify it like this in another dependency unless you explicitly re-require all the depedency's dependencies.Tarter
S
138

At the time of writing in 2013, this was one way to do it. Composer has added support for better ways: See @igorw 's answer

DO YOU HAVE A REPOSITORY?

Git, Mercurial and SVN is supported by Composer.

DO YOU HAVE WRITE ACCESS TO THE REPOSITORY?

Yes?

DOES THE REPOSITORY HAVE A composer.json FILE

If you have a repository you can write to: Add a composer.json file, or fix the existing one, and DON'T use the solution below.

Go to @igorw 's answer

ONLY USE THIS IF YOU DON'T HAVE A REPOSITORY
OR IF THE REPOSITORY DOES NOT HAVE A composer.json AND YOU CANNOT ADD IT

This will override everything that Composer may be able to read from the original repository's composer.json, including the dependencies of the package and the autoloading.

Using the package type will transfer the burden of correctly defining everything onto you. The easier way is to have a composer.json file in the repository, and just use it.

This solution really only is for the rare cases where you have an abandoned ZIP download that you cannot alter, or a repository you can only read, but it isn't maintained anymore.

"repositories": [
    {
        "type":"package",
        "package": {
          "name": "l3pp4rd/doctrine-extensions",
          "version":"master",
          "source": {
              "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
              "type": "git",
              "reference":"master"
            }
        }
    }
],
"require": {
    "l3pp4rd/doctrine-extensions": "master"
}
Solemn answered 18/10, 2012 at 11:56 Comment(13)
Replacing the VCS repository with a package repository is a bad idea. The target repo already has a composer.json, so use a vcs repo. Your example also breaks autoloading and ignores the branch-alias.Heber
@Heber can you please link to that information so that I and other can understand the difference? Thanks.Solemn
As explained on the repositories page a package repo must include all information. If you don't add the autoload field, it will not be included. Basically you need to copy-paste all info from composer.json to the repo definition. The VCS repo fetches that info from VCS directly. The benefits of branch-alias are explained in the aliases doc and a blog post I wrote.Heber
you should the version instead of 'master' linkDispart
Why is this still being upvoted? The composer docs even explicitly state that package repos should be avoided. Please, stop encouraging bad practices.Heber
What do you recommend I change it to then ?Solemn
The priority is as follows: packagist, vcs, package. Package repositories are a last resort.Heber
@Heber I made this a community wiki so you can put the best practice in here and bad practices wont be encouraged.Solemn
I would like to point out that I found this post and its comments valuable because it highlights a bad practice I easily could have stumbled into.Hypochondrium
Thanks to the package feature i don't have to force needless complexity on other repos. master#commit should emulate submodules pretty well. Version numbers can be hacked.Medullated
I'm looking to this solution to store hacked code. We often depend upon a package that is no longer maintained. There simply isn't another package out there that's as good as this one - but we've had to modify it a few times to make it do everything the way we want. If not for a this solution, what the best practice?Bethanie
Good answer for the backtrack, usually if the library does not have a composer.json file as you mention , it ends up with the error 'No valid composer.json was found in any branch or tag'Tarter
Man Your comment is valid till the last day on earth simply because sometimes there is old packages that have issues and no longer gets updates from it's developer so as a developer i just download the code and fix the issues then push it to git repo and pull it when needed that saves me alot of time instead of fixing the package issues every timeUralian
S
54

You can include git repository to composer.json like this:

"repositories": [
{
    "type": "package",
    "package": {
        "name": "example-package-name", //give package name to anything, must be unique
        "version": "1.0",
        "source": {
            "url": "https://github.com/example-package-name.git", //git url
            "type": "git",
            "reference": "master" //git branch-name
        }
    }
}],
"require" : {
  "example-package-name": "1.0"
}
Stroll answered 11/12, 2014 at 13:14 Comment(4)
As explained in the other answers above: If you have a repository, add a composer.json file if at all possible.Fiery
@Fiery ...because it's impossible to specify a specific commit otherwise?Medullated
Thank you for sharing, saved me hours :)Islamism
This is adjusted to be general, but otherwise basically a plain copy of the Mike Graf's answer, so I am not sure if general is better than seeing a particular library in the question as an example.Tarter
T
12

I try to join the solutions mention here as there are some important points to it needed to list.

  1. As mentioned in the @igorw's answer the URL to repository must be in that case specified in the composer.json file, however since in both cases the composer.json must exist (unlike the 2nd way @Mike Graf) publishing it on the Packagist is not that much different (furthermore also Github currently provides packages services as npm packages), only difference instead of literally inputting the URL at the packagist interface once being signed up.

  2. Moreover, it has a shortcoming that it cannot rely on an external library that uses this approach as recursive repository definitions do not work in Composer. Furthermore, due to it, there seems to be a "bug" upon it, since the recursive definition failed at the dependency, respecifying the repositories explicitly in the root does not seem to be enough but also all the dependencies from the packages would have to be respecified.

With a composer file (answered Oct 18 '12 at 15:13 igorw)

{
    "repositories": [
        {
            "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
            "type": "git"
        }
    ],
    "require": {
        "gedmo/doctrine-extensions": "~2.3"
    }
}

Without a composer file (answered Jan 23 '13 at 17:28 Mike Graf)

"repositories": [
    {
        "type":"package",
        "package": {
          "name": "l3pp4rd/doctrine-extensions",
          "version":"master",
          "source": {
              "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
              "type": "git",
              "reference":"master"
            }
        }
    }
],
"require": {
    "l3pp4rd/doctrine-extensions": "master"
}
Tarter answered 15/7, 2020 at 15:29 Comment(0)
D
9

Just tell composer to use source if available:

composer update --prefer-source

Or:

composer install --prefer-source

Then you will get packages as cloned repositories instead of extracted tarballs, so you can make some changes and commit them back. Of course, assuming you have write/push permissions to the repository and Composer knows about project's repository.

Disclaimer: I think I may answered a little bit different question, but this was what I was looking for when I found this question, so I hope it will be useful to others as well.

If Composer does not know, where the project's repository is, or the project does not have proper composer.json, situation is a bit more complicated, but others answered such scenarios already.

Derivative answered 12/7, 2016 at 21:19 Comment(1)
I came here looking precisely for this, thanks! Though I think you need to use require--it doesn't work with install.Chalkboard
B
4

I was encountering the following error: The requested package my-foo/bar could not be found in any version, there may be a typo in the package name.

If you're forking another repo to make your own changes you will end up with a new repository.

E.g:

https://github.com/foo/bar.git
=>
https://github.com/my-foo/bar.git

The new url will need to go into your repositories section of your composer.json.

Remember if you want refer to your fork as my-foo/bar in your require section, you will have to rename the package in the composer.json file inside of your new repo.

{
    "name":         "foo/bar",

=>

{
    "name":         "my-foo/bar",

If you've just forked the easiest way to do this is edit it right inside github.

Bully answered 27/6, 2015 at 23:19 Comment(1)
Note that the package name does in no way reflect the URL from where you can read the repository! There is no automatic link between the two, both can be chosen independently. The only relevant information regarding Composer is the name written into the name attribute inside composer.json.Fiery
D
2

In my case, I use Symfony2.3.x and the minimum-stability parameter is by default "stable" (which is good). I wanted to import a repo not in packagist but had the same issue "Your requirements could not be resolved to an installable set of packages.". It appeared that the composer.json in the repo I tried to import use a minimum-stability "dev".

So to resolve this issue, don't forget to verify the minimum-stability. I solved it by requiring a dev-master version instead of master as stated in this post.

Darwinism answered 13/11, 2013 at 13:41 Comment(1)
I had the same issue, which is discussed here. If you have an explicit ref (like a git commit), it appears you can do something like "dev-master#4536bbc166ada96ff2a3a5a4b6e636b093103f0e".Marrs
D
1

If you want to use a composer.json from GitHub you would look at this example (under the VCS section).

The package section is for packages that do not have the composer.json. However, you didn't follow that example as well or it would also have worked. Do read what it says about package repositories:

Basically, you define the same information that is included in the composer repository's packages.json, but only for a single package. Again, the minimum required fields are name, version, and either of dist or source.

Daub answered 18/10, 2012 at 12:51 Comment(0)
M
-1

https://mcmap.net/q/159197/-use-php-composer-to-clone-git-repo

{
    "repositories": [
        {
            "type":"package",
            "package": {
              "name": "tiagof2/materializecss-laravel-pagination",
              "version":"v1.0.3",
              "source": {
                  "url": "https://github.com/tiagofrancafernandes/materializecss-laravel-pagination.git",
                  "type": "git",
                  "reference":"v1.0.3"
                }
            }
        }
    ],
    "require": {
        "tiagof2/materializecss-laravel-pagination": "v1.0.3"
    },
}
composer update
Mertens answered 17/8, 2022 at 2:5 Comment(3)
Why did you copy/paste the accepted answer?Obelize
I did not do this. This is standard for package creation. This is the composer.json of a package, see for yourselfFellow
Ok sorry, I thought that because this is the same code as the accepted answer, only 9 years later.Obelize

© 2022 - 2024 — McMap. All rights reserved.