Can we use Composer with sparse SVN checkout to share dependencies? - php

Our current development setup uses a single Subversion repository containing multiple projects, each with branches, tags, and trunk. We then use a "sparse checkout" to select the projects, and branches of those projects, to work with.
The result is that the directory structure of a working copy matches that of the repository, including branch information, and we never use svn switch. (This style of working will probably be familiar to anyone who uses SVN, but may be surprising to those who don't.)
We are thinking of using Composer to manage both external and internal dependencies, but I'm not sure how this can work with the sparse checkout style of working.
I would like some way of using a directory within the existing checkout to satisfy a dependency, rather than each "root project" needing a separate copy.
For example:
sites/Foo/trunk
depends on lib Aaa, so references lib/Aaa/trunk
depends on lib Bbb 1.5.*, so references lib/Bbb/branches/release-1.5
sites/Bar/trunk
depends on lib Aaa 1.0.*, so references lib/Aaa/branches/release-1.0
depends on lib Bbb 1.5.*, so references lib/Bbb/branches/release-1.5
At present, if I edit the code in lib/Bbb/branches/release-1.5, I can test those changes on both sites, without needing to commit one and update the other.
Is there any way of using Composer to manage these dependencies?
(PS: Please don't answer with "give up on SVN, use Git, it is teh awesomez"; that is an answer to a different question.)

No - I do not believe that you can do this with Composer as standard: it expects to copy the files from whichever source (Packagist/VCS/Zips) to the local vendor folder, which is not what you want.
That said, I believe there are two potential ways you could get this working (at least in part):
Autoloader
You could try using the autoload field in the composer.json file to include the correct files into the project. You would still need to manage the checkouts of the relevant branches/versions manually (like I assume you do now), but you would be able to manage the inclusion of the internal libraries through Composer. This will probably require that your libraries are properly namespaced. The paths to the files for each namespace are relative to the root of the project, but can go below the root (via the /../ path) if required.
To be honest though, if you already have an autoloader for these files, there may not be much advantage to this solution. Relevant Docs
Composer Plugin
You could also write a composer plugin/"custom installer" that could probably manage this. This would have the advantage that you could have it manage checking out the correct parts of the sparse repository to have the correct version available, as well as doing correct wildstar version checking, but would be a much more difficult and riskier venture.
The basic process would be that you would define a new package type (e.g. 'internal-svn-package'). You would create the plugin as an external library that gets installed normally via Composer, which declares (via it's composer.json) that it handles this new type of package. Your custom logic would then be used for any packages that are listed with this custom type. I'm not sure how much of the internal composer logic for SVN checkouts you would be able to reuse however. Relevant Docs

Related

PHP, GIT, Location for reusable components

Thanks for your attention, this is a question of organization, I work with PHP and GIT for version control. I use Netbeans IDE to program, GIT integrated (although I am still a rookie).
Normally, I follow the approach that Symfony2 specifies for organize the project files, but I use my own framework for my projects.
The (main) question is: Any component or code part which has its own version control must be located under the /vendor/directory?
For example:
I have my project files in src\Acme\ProjectX\, also the utility package which use all my projects: src\Acme\Util\, and it is under the version control too (GIT).
and now let's remember the basic skeleton of a project based on Symfony or similar:
/app (application related elements)
/src (source code of the project)
/vendor (third party libraries)
/web (front end controller, the web directory, assets resources etc...)
So, Must be 'Acme\Util' included in the vendor directory? And, is necessary to use composer to declare the dependences?
In addition, the Utility package has a lot of classes but only few are used in projects. Must I remove those are not using by the project.
Summarizing, It will be nice if someone can contribute his knowledge for help me to represent an scenario like this.
I hope I could explained...
Thanks in advance!
Vendor directory
It's a good practice to separate external dependencies and the application code. If you are using Composer you can change it to something else.
Unused classes
Unused classes shouldn't matter if they aren't being loaded. They'll just take a bit of extra disc space.
It might be a good idea to separate the Utility package into multiple packages if you find yourself frequently using only a small part of it.
Dependency managers
It isn't necessary to use a dependency manager, but it sure does help. Having to install, configure and maintain everything manually (especially with many dependencies and sub-dependencies) would be a horror.

Working on dependent, unpublished libraries with Composer

Let me first describe what I'm doing:
I'm working on two libraries, call them A and B - neither of these are public anywhere, and I don't want to publish them until they're stable.
Library A depends on Library B.
These two libraries are in separate, local Git repositories, and have individual composer.json files.
My problem is this: during development, I need a way to specify the dependency on Library B in Library A - which is simple enough, it's just an entry in the "require" section of Library A, and since nothing is versioned or committed yet, I'm specifying "dev-master" as the version requirement.
The issue is, library B of course does not really "exist" anywhere yet, as this is all local development on local Git repositories.
What I don't want, is I don't want to have to commit changes to Library B and having to do a composer install for Library A for every incremental change.
In fact, I don't want to "install" library B at all, as long as I'm just working on the repositories locally - that is, I don't want copies of Library B in Library A's vendor folder, I just want the generated auto-loader for Library A to point directly to my local Library B folder.
Surely there must be a way to do this? I have spent half a day searching and reading the documentation, blog posts, third-party guides, stack overflow questions, etc. - and found nothing.
Isn't this a totally common scenario and requirement for pretty much any developer?
Ideally, I also would like to be able to do this with a local file somehow - that is, I would rather not have to pollute my composer.json file with settings that are only relevant to me while I'm developing. But this is secondary - I can live with having to "hack" my local composer.json and avoid checking in the changes during development, but I cannot live with having to commit and install/update/copy files with every incremental change.
Any ideas?
It's not that common I think that people work on two brand new libs at once, but I agree we should support this better somehow.
I think the easiest/only way to do this is to install libB in libA using a local VCS repository definition (file:///path/to/foo/.git works), and then replace vendor/lib/A by a symlink to libA's folder. Just be careful if you run update because I'm not quite sure what happens in that case.
The other less pretty but perhaps easier way is to just develop libB in the vendor dir of libA, you can run install in libB's folder to get any dev dependencies. It's a bit ugly but not so dramatic IMO.

Is there a simple way to remove composer from an app or a framework

For example, if I want to remove composer from fuelphp... is there any easy way to remove composer?
I mean I ask to use fuelphp (or some framework else) without composer.
Since composer is part of the framework. You "Do" need it. Period. Otherwise you have to follow #Sven's advice.
Having said that, you often only have a need for composer on your development platform, since that is where you'll want to pull the new code or updates in.
It's perfectly fine to deploy your application (to a staging or production environment) without composer, and without the .git folders. You would not want to have updates pulled in in those environments anyway, all code on these platforms should be under your version control.
No, there is no "simple" way.
To do what Composer does, you'd need to have:
Download all the libraries in the correct version that are directly included.
Also download all libraries that are required by any library in step 1.
Repeat downloading new libraries in step 2 unless you do not find any new, i.e. you completely downloaded all these.
Then create an autoloader for every downloaded library depending on what every configuration for every library said has to be done, i.e. either register a PSR-0 (or PSR-4 if some libs like to live on the edge), or parse the whole source tree for occurrences of classes, interfaces and traits and create an array listing every such class name and the containing file name.
Last but not least find a way to place everything downloaded and created where the regular Composer results would be expected.
Doing this manually is not impossible, but it is ridiculous to do so.
While I do admit that Composer makes it a little bit harder for the uninformed hobbyist programmer to fiddle with his home-brewn scripts when trying to download a new library because he now has to get to know Composer, in the end it makes the lives of everyone much easier - the time invested into getting to know Composer is well invested. Composer will not go away soon. In fact, every other language has something like Composer for a very long time, and nobody complains or tries to remove these dependency managers there.
FuelPHP from version 1.7+ (I think) requires composer, you would have to modify the autoloader to prevent it from trying to use composer's autoloader. This is not advisable as it means it becomes harder to keep up to date with maintenance releases.
Unfortunately for you composer is rather widespread and so is something that you will have to use if you continue working with frameworks. Fuel ships with a version of the composer.phar so you don't even have to go to the bother of downloading/installing it on your system.
If there is no dependencies, you can always simply do something like :
set_include_path(dirname(__FILE__).'/framework_XYZ');
spl_autoload_extensions(".php");
spl_autoload_register();
without forgetting to change the "framework_XYZ" by the directory where the core/system classes are hiding... ;)
J.

How can I safely add to a composer package?

I am using the Composer package Omnipay in my project and I want to add a new class to the package (in my case it is support for a new payment gateway). The naming does not conflict with anything and it follows the same naming and structure conventions as sibling folders. However, when I run composer update it deletes my whole folder of changes even though it didn't need to. Is there a way I can tell composer not to delete that directory?
Leave everything under /vendor alone, don't change any files there. You should treat libraries as external dependencies - don't check them into source control or change them in any way. Just reference them in your own code.
If you need to customize a composer library, you can either work around it in your own code (most PHP libraries support dependency injection, which will let you override any of the libraries' classes), or alternatively you can fork the library on github, then reference your own fork in composer.json, or submit the pull request so everyone can benefit from it.
As far as I'm aware, you cannot add to a Composer package as it is external and therefore out of your control. You should treat the packages as libraries only, and add all classes into your own project, ensuring that the packages you need are still set up in your .json file

process for creating and applying svn patch

I am using a 3rd party library as part of my code base. It has a bug and i have 2 choices:
Create and overridden class to provide the big free behaviour.
Create an svn patch for the bug
I prefer 2 because logically it makes more sense, however i am not sure of how to do this,
Do i do the following:
Modify the 3rd party library code
Create the patch file
revert my repository
Apply the patch file
Add the patch file to the repository
Commit my changes
??
If i should use a patch, where would this be stored in the repository?
Check for Vendor Branches:
But sometimes you want to maintain custom modifications to third-party code in your own version control system. [...] These modifications might include new functionality or bug fixes, [...].
Now you face an interesting situation. Your project could house its custom modifications to the third-party data in some disjointed fashion, such as using patch files or full-fledged alternative versions of files and directories. But these quickly become maintenance headaches, requiring some mechanism by which to apply your custom changes to the third-party code and necessitating regeneration of those changes with each successive version of the third-party code that you track.
A vendor branch is basically a directory (we call it A) with the unmodified version of your source code. You branch this directory into your project (or any other location, we call this X) and apply your path to this branch. If vendor updates his component you will import it into a directory (we call B). To update your own modified library you will do a merge between B and A and apply this to X. In this way you keep your modification but also get all changes between vendors software versions.
Keep in mind to use --ignore-ancestry option on merge command otherwise you will replace changed files and not apply the diffs

Categories