New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symlink local development libraries #1299

Closed
Petah opened this Issue Nov 7, 2012 · 32 comments

Comments

Projects
None yet
@Petah
Contributor

Petah commented Nov 7, 2012

Is there any way to simply symlink a vendor library from another directory rather than keeping a local copy for each project?

This is primarily for speed of development.

We have many in house modules (20-30) and are running a Satis server.

When we require a change to a module for a project, you must follow this process at present.

  • Make change in module
  • Commit and push change to Git server
  • Update Satis server (currently on a 5 min cron schedule)
  • Update the project using composer update --dev

The turn around on this is quite lengthy, and doing it multiple time for multiple modules/projects is impractical.

If we could just symlink each of our in house libraries into the vendor directory, turn around time would be nil.

@johnkary

This comment has been minimized.

Contributor

johnkary commented Nov 9, 2012

Feature request #55 to allow system-wide install of packages may be relevant here.

@mneuhaus

This comment has been minimized.

mneuhaus commented Nov 9, 2012

i'd love something like this as well.

#55 does not solve this case in my opinion, because it only focuses on providing a global bin for phpunit and similar stuff.

In my case i've got several Development Environments on my machine which share quite some Packages i'm working on. It's getting quite annoying to keep them up to date through push&pull, especially, since i partly want to test it first in different environments before pushing. I tried to solve this by manually making symlinks for those packages form a central location to the environments, but just a few minutes ago a 'composer update' acutally deleted one of my pending local copies in in the process :/

@stof

This comment has been minimized.

Contributor

stof commented Nov 9, 2012

What you want seems to be #1017 in fact

@ecolinet

This comment has been minimized.

ecolinet commented Mar 26, 2013

Hi there,

+1 for this issue.

For us Composer is great when building applications. But when our projects goes in production on our internal shared hosting (100+ projects by server), the projects should use a shared version of the main dependencies they are using (ZF, Doctrine).

It's important for us to share the code because without that the opcode cache is quickly full with the same huge files (say Zend_Date).

So for us the ability to have a global repo that can be referenced in local projects is a top requirement for the global adoption of Composer.

Btw, thanks for your work,
Eric

@jaapio

This comment has been minimized.

Contributor

jaapio commented Apr 4, 2013

@gossi

This comment has been minimized.

gossi commented Jun 9, 2013

👍

I think that a local location to look for dependend packages and the global installation (#55) for packages would work well together.

I have an idea for this. For this, composer needs to know where to fetch local dependencies. A simple directive to point to a folder (see option 1 and 2 below). And this is how composer searches for dependencies:

  1. Search for the package in the given local folder (symlink to vendor/ folder, ignore version constraints, since these are meant for development)
  2. Search for the package in the global folder (symlink to vendor/ folder)
  3. Search the other sources for the package

Two different local directives:

Option 1: Short Syntax

"config": {
    "local": "path/to/local/folder"
}

Composer would then expect the local folder to contain packages in the / format:
E.g. a dependency of "A/B" would then be looked up in "path/to/local/folder/A/B".

Option 2: Detailed Syntax

"config": {
    "local": {
        "": "path/to/local/folder",
        "<vendor>": "path/to/another/folder/<vendor>"
    }
}

This one is a little more fine grained, as it gives you control to where to look up a certain vendor. Without a given as key, this option would behave as option 1 (so, both syntax are actually possible and valid).

Benefits
Run the update/install command only ONCE and you can use your local dependencies (since they are symlinked, they update on-the-fly). Once you commit your dependencies and you install it from a different location (another machine) the normal dependency strategy takes in effect.

@goetas

This comment has been minimized.

goetas commented Aug 3, 2013

I think that this feature should be configurable from an external file, something like dev.json.dist and included trought composer.json.
composer.json.dist

...
"config": {
    "dev-libs": "dev.json"
}

dev.json

{
        "<vendor>": "path/to/another/folder/<vendor>",
        "<vendor>": "path/to/another/folder/<vendor>"
    }

This because each developer can have a different environment and libraries placed in different locations.

@smazurov

This comment has been minimized.

smazurov commented Apr 18, 2014

👍

1 similar comment
@dermellor

This comment has been minimized.

dermellor commented May 4, 2014

👍

@coldcandor

This comment has been minimized.

coldcandor commented May 13, 2014

I was just talking with my dev team about this exact issue. Great to see that it's already got traction!

@Petah

This comment has been minimized.

Contributor

Petah commented May 13, 2014

I don't know if traction is the right word, I don't think it actively being worked on.

@coldcandor

This comment has been minimized.

coldcandor commented May 13, 2014

Community traction is what I meant. Obviously having the actually dev team work on a fix would be much better...

@torches

This comment has been minimized.

torches commented Jul 9, 2014

+1 This is a pain while working on a modular system that has multiple dependencies.

@joeholdcroft

This comment has been minimized.

Contributor

joeholdcroft commented Jul 9, 2014

If anybody needs a kinda decent way of doing this in the meantime, #1324 introduced a method to the autoloader to override the path to a namespace which you can use to intercept the autoloader to achieve a similar thing. For example, I'm adding a namespaces.php file to the root of my project that includes the Composer autoloader and then changes whatever paths I want to override:

<?php

$autoloader = require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';

$autoloader->setPsr4(
    'VendorName\\PackageName\\',
    '/code/vendor-package/src'
);

return $autoloader;

If your app needs the autoloader instance for any reason you can just use the result of including this file rather than vendor/autoload.php.

I keep a bunch of my common overrides in there that point to my local repositories and just comment them out & uncomment them as I need. It's worth ignoring this file in version control. The downsides are that you need to know the namespace and you need to call a different method depending whether it uses PSR-0 or PHP-4, but it's something!

@torches

This comment has been minimized.

torches commented Jul 11, 2014

@joeholdcroft Thanks for the example, this certainly helps :)

@ammont

This comment has been minimized.

ammont commented Jul 27, 2014

+1 for this, it would be very useful.

@mbrevda

This comment has been minimized.

mbrevda commented Dec 16, 2014

+1

@Jeremlicious

This comment has been minimized.

Jeremlicious commented Jan 21, 2015

+1

1 similar comment
@gilbitron

This comment has been minimized.

gilbitron commented Mar 5, 2015

+1

@e-picas

This comment has been minimized.

e-picas commented Mar 15, 2015

Hello all,
I made a plugin for that (not so amazing but it works fine) : https://github.com/piwi/composer-symlinker.
If it helps ...

@jreinke

This comment has been minimized.

jreinke commented Apr 2, 2015

Hi there,

@piwi solution did not work for me because my local packages are not under VCS.

So I had to modify Composer itself to allow local packages installation, modification is quite simple jreinke@92ad4e4. You have to modify your composer.phar like that:

$ git clone https://github.com/jreinke/composer.git && cd composer/
$ curl -sS https://getcomposer.org/installer | php && php composer.phar install
$ ./bin/compile

Now you can use custom composer.phar for local packages installation like below:

"require": {
     "<vendor>/<local-package>": "*"
},
"repositories": [
    {
        "type": "folder",
        "url": "../path/to/package/"
    }
]

Local packages are installed with symlinks so that any modification made is automatically applied to projects depending on them.

@Vittel

This comment has been minimized.

Vittel commented Apr 3, 2015

Hey,

just a complain: having symlinks in anything related to source control is not a good idea. Why dont you just read the packages from where they are and not link them in?

@jreinke

This comment has been minimized.

jreinke commented Apr 3, 2015

I agree, but symlinks are also a good way for developers productivity. Hard copying packages would involve frequent composer update commands on all depending packages.
Maybe a good option would be having the choice between hard copy and symlink...

@Vittel

This comment has been minimized.

Vittel commented Apr 3, 2015

No, i mean do not copy or link them at all. just take the position of the sourcecode as is, and do include the files in their original position in the autoloader

@Divi

This comment has been minimized.

Divi commented Apr 6, 2015

If someone can't wait for this feature, I made a plugin to automatically symlink only dev packages : https://github.com/Letudiant/composer-shared-package-plugin

Hope it can help.

Btw 👍 for the native implementation.

@jreinke

This comment has been minimized.

jreinke commented Apr 6, 2015

Nice alternative @Divi, thanks for sharing.

@iwiznia

This comment has been minimized.

iwiznia commented Apr 8, 2015

@jreinke that would be a great addition. Will try it and let you know if it works. Why not make that a pull request? Lots of people are asking for something like that.

@gossi

This comment has been minimized.

gossi commented Apr 9, 2015

I wrote a blog post about my discovery with local composer development. I also summarized some of the requirements and ideas I came across while dealing with local development.

Please take a look: http://gos.si/blog/composer-development-with-local-dependencies

@Divi

This comment has been minimized.

Divi commented Apr 9, 2015

Nice post @gossi, pros & cons are nicely resumed.
Just one comment about the first pro for symlink workaround (fetching each repository composer.json file) : you can handle it by installing Satis, see : https://github.com/Letudiant/composer-shared-package-plugin/blob/master/docs/how-to-use/work-with-satis.md

You can even disable packagist to use only your Satis host.

@ahuszko

This comment has been minimized.

ahuszko commented Nov 27, 2015

This may help you to improve local package development: http://ahuszko.ghost.io/compact/

@staabm

This comment has been minimized.

Contributor

staabm commented Nov 27, 2015

@Seldaek I think we can close this one, because we have PathRepository now?
https://getcomposer.org/doc/05-repositories.md#path

@Seldaek

This comment has been minimized.

Member

Seldaek commented Nov 27, 2015

Closing as duplicate of #601 anyway, but yes path repo helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment