I'm not sure how to approach this issue, since it's a little more than a mere patch, so I'll just start typing ;-)

I really like Drush. Being able to work my Drupal sites from the command-line fits my style perfectly. But one thing has been nagging me ever since I started using Drush: why do I have to install all those modules on each and every site?

In my work I deal with many installations for many customers. Some are fairly simple sites, barely more than theming and some CCK/Views/Panels configuration. And some installations are stretching Drupal to the very limit, involving elaborate multi-site setups with dozens of domain names, databases and complex custom modules. Having to maintain an extra module across all those configurations almost nulls the advantage. Well, not quite, but close enough to bother.

What nags me is, that it really isn't necessary. As far as I can tell, in principle there is nothing in Drush that actually needs to be a module in order to work it's magic. It stands to reason: The whole point of Drush is to make Drupal believe it is being invoked by a webserver. If some part of Drush really needed to be a bona fide Drupal module, the Drush framework could install it, all by itself, including copying files to the right places, running install scripts against the database and what have we. After all, I'm the developer of the site: I can already do all that, by other means. It's my job.

Well. Enough "complaining" ... because it really is possible. I have made my own private fork of Drush that works transparently with all the pre-packaged modules! It took a bit of hacking, but after a few trials, the solution is actually quite simple. It goes roughly like this:

* I made a copy of the Drush package in a directory outside of any Drupal installation.
* I moved all "drush_*" folders into a newly created "modules" folder within my new Drush folder.
* I added a drush_module_invoke_all (and a few related functions) that essentially paraphrases Drupals own module_invoke_all.
* I made drush_get_commands use this new function.

And that's it! More or less. It works perfectly in my environment (Ubuntu) and should work with no effort on Mac OS X. I have not tested it on Windows. In all other respects, Drush works exactly like before.

I have also added a little extra feature: if you invoke drush in a particular site folder beneath a Drupal root, it tries to make sense of the folder name and sets the 'l' option accordingly. That way, you simply jump into the site folder of interest and starts working it's magic. It's quite convenient, provided that you name your site folders like you're supposed to.

With this "patch", we can also start making commands that work across sites in the same installation. That could turn out to be a real time-saver.

And last, but not least: it works across Drupal major versions. I have not tested this extensively, but quite a few of the commands I use frequently work across Drupal 5 and 6. This aspect should be considered explicitly, though.

I have attached my "fork" to this post, and I would really appreciate comments of all kinds. You simply unpack it into any folder on your system and invoke drush.php like you would anyway. It is based on Drush 6.x-1.1 and contains all the same additions in the "modules" folder. Beware, however, that this is a working draft and it still needs a little work. For instance, drush_module_invoke_all should fall back to module_invoke_all, so as to get drush commands implemented in larger Drupal modules (e.g. the Devel module).

Kind regards
vingborg (Jesper Vingborg Andersen)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

vingborg’s picture

Naturally I didn't bother to check the open issues, but this is pretty much a possible solution to the issue raised in #222187: Single drush for multiple drupal installations. It goes without saying that I believe in the viability of the idea, especially if drush_get_commands also calls module_invoke when compiling the list of commands, if possible (i.e. if there is an active site). That way, we get the best of both worlds.

I'm not too keen on the idea of one drush across major versions of Drupal, as it has the potential to introduce a lot of confusion, but I must admit that it's quite handy at times.

//vingborg

moshe weitzman’s picture

Status: Active » Needs review

Sure, we've all been interested in this for a long time.

A few tips:

* next time, please try to be brief in your description.
* please make a new module.inc file which holds functions like drush_module_implements(). that way we can see how the new module engine works.

vingborg’s picture

moshe, sorry about the "novel". This is my first real attempt at participation in the Drupal community, so I'm a bit unsure about how to mingle with you guys. Anyway, I think I'll post a cleaner version along your suggestion in a short while, so please watch out.

vingborg’s picture

FileSize
4.68 KB

I read up on proper procedure and made a patch against the DRUPAL-6-1--1 tag as of a few minutes ago. Contrary to my earlier braindump (sorry about that, people), it contains the minimal changeset for making drush run without installing/enabling any modules, and only that.

Highlights:

  • drush.php doesn't exit if it isn't installed as a Drupal module (obviously;-)
  • All drush module handling is found in module.inc
  • drush.inc uses the function in said module.inc instead of those from Drupal core
  • It checks for a successful Drupal bootstrap and loads "traditional" drush commands if possible

I hope you guys will check it out. If you put it in, I will port it to the 5 and 7 branches ASAP.

moshe weitzman’s picture

This is looking very interesting. I'll give it a test when I get a chance. I hope others do too. Meanwhile, please include any documentation changes that are needed (README, example.drushrc.php?). Also, the glob() function is not universally available. D7 just remove it in favor of some workaround - i don't recall the details.

swentel’s picture

This is exciting. Most things allready work smoothly. After I changed module_invoke_all to drush_module_invoke_all in the drush_pm_module, I could even install packages into my drupal 6 directory while running drush from a directory in my home dir. Very nice and this way the drush_pm module can get rid of the requirements hook. Or change this to our own requirements hook to check if a module is enabled on the site we are looking at, because things won't work if simpletest module isn't installed for instance. I'm going to play with it more and try to update the patch to see what needs to be changed more.

adrian’s picture

I love the patch so far.

I'm busy finishing up a version of the patch here.

The mask is far too restrictive, and glob is not the right function to use.

In the patch i am finishing up, I copied file_scan_directory, so we can have nested searches.
I have changed it to load *.drush.inc files (instead of the module files), and I am busy moving all the actual commands into their own .drush.inc files (this is easy, but slightly time consuming).
I also added a --include or -I option, that allows you to specify additional search paths to find drush commands.

I've actually got this working for installing sites using aegir (groups.drupal.org/aegir). We are by far the most complex users of drush, and this patch makes our lives a _LOT_ easier.

adrian’s picture

Status: Needs review » Needs work
adrian’s picture

Status: Needs work » Needs review
FileSize
100.36 KB

Here is the patch as promised :

1. Drush now loads *.drush.inc files
2. You can specify additional paths to search using -i or --include (documentation has been updated too)
3. All module files are split into MODULENAME.drush.inc and MODULENAME.module files. (the .module files might become irrelevant if we decide to ignore the hook_help implementations).

moshe weitzman’s picture

I support the extensions that Adrian has added. Nice work. I'd love to see:

* README.txt updated
* Someone has to commit to updating HEAD. We can't let that fall behind for very long. I'm much less concerned about backport to 5. If someone wants to do that, then I'll commit it in a new branch but it really isn't needed IMO.

Owen Barton’s picture

This looks really good!

I started testing it out, but realized that module.inc is missing from adrian's patch. Rather than starting from the one in the previous patch and trying to deduce the changes I figured it would be quicker to just reroll.

Some thoughts/questions:
1) Am I right in assuming that if modules implement drush commands they will still be available via the regular hooks as long as that site gets bootstrapped? I think this would be very useful for commands that are part of some more complex general purpose system that you might not want on every site.
2) If (1) is the case then am I correct that if you wanted to add a module to your "system" drush installation you could just copy it to somewhere below your drush directory?
3) If (3) is also the case then are there any helper functions we would need to write so that modules could operate correctly?
- How would dependencies be handled?
- What if the module needs some installation to work at all?
- Would modules just need to be specially written to support this (i.e. to operate mostly independently and check for any dependencies at runtime)?
- What happens if the code is both in the system drush directory, and also the site modules directory - how do we prevent it running twice?

The last actually has a more general case - what happens when I try and run the "system" drush on a site that already has drush installed in the old way - are we preventing it getting included twice?

adrian’s picture

FileSize
5.02 KB

Sorry about that, i only added Entries for the files I added. Didn't realize module.inc wasn't included.

adrian’s picture

Status: Needs review » Needs work

I would have re-rolled , but my tree is not pristine right now. I used this patch as the basis for an experiment to see if i could make drush run in DRUPAL_BOOTSTRAP_CONFIGURATION. I added a 'bootstrap' level to the hook_drush_command structure, so you can specify the level to initialize at.

It worked. This patch is the first step in being able to write an install command for drush, which mimics the functionality of install.php.

Am I right in assuming that if modules implement drush commands they will still be available via the regular hooks as long as that site gets bootstrapped? I think this would be very useful for commands that are part of some more complex general purpose system that you might not want on every site.

not at present, we'd need to have our own implementation of system_listing to pick up commands in the enabled module trees. It would essentially add more directories to --include. I don't think there should be multiple places to add drush commands (such as either in .modules or .drush.inc), but the modules will be loaded as part of DRUPAL_BOOTSTRAP_FULL.

2) If (1) is the case then am I correct that if you wanted to add a module to your "system" drush installation you could just copy it to somewhere below your drush directory?

Yes. as long as you also specify the path in --include, either on the command line or the drushrc.php.

3) If (3) is also the case then are there any helper functions we would need to write so that modules could operate correctly?
- How would dependencies be handled?

Drush commands could check that the module they require exists. I suggest adding a 'depend' entry to drush_command, and make the help command respect that when showing available commands. This is a per command thing for me. Part of this would tie into the drupal_bootstrap level, so that if a site isn't initialized, it will only show commands available at the BOOTSTRAP_CONFIGURATION level.

- What if the module needs some installation to work at all?

Having the commands depend on modules being enabled would solve that.

- Would modules just need to be specially written to support this (i.e. to operate mostly independently and check for any dependencies at runtime)?

Well. at the very least, I think they should have a *.drush.inc if they want any drush commands whatsoever. I'm currently including the .drush.inc in the module file, so more complex systems could do the same.

- What happens if the code is both in the system drush directory, and also the site modules directory - how do we prevent it running twice?

As i mentioned, we should copy system_listing, to match how drupal detects what modules it is running. To stop multiple command sets from being loaded we will use the same mechanism Drupal uses, ie: index the files array with the basename, not the filename.

Anyway, this patch is important to the Aegir project. We were on the verge of dropping drush in the next release, because it simply requires too much to get up and running. You can't use it to install a site until you have at least one running, which meant for every
drupal release, you would need a database, and a virtual host configuration and manually go through the install, before you could use
it to deploy other sites.

This with the extension if being able to specify what level to run at while initializing, will allow us to write drush commands that can initialize and install sites, without having to load an initial site and then switch active databases (which is a really ugly hack to begin
with). I am actively maintaining Drupal 5 and Drupal 6 trees of provision (http://drupal.org/project/provision), but until i make a final 0.1 release of those projects, I can't contribute much time to a Drupal 7 version of this patch.

Perhaps we should consider this the start of a 2.x branch for drush ?

vingborg’s picture

What timezone are you guys working in?

@adrian: you're right about the search mask and using glob. I was aiming at the minimum possible changeset, but was about to dig into how Drupal core does the same thing. Seems I won't have to, now. Cool.

@grugnog2: My original patch (in comment #4) would actually check for the existence of module_invoke (i.e. Drupal bootstrapped) and add commands to the list, just like drush did before. I haven't checked if that made it into adrians patch, but it's only a few extra lines of code.

In general, I think that keeping drush modules and drupal modules as close as possible in structure would be preferable for a couple of reasons: 1) it will be much easier to write ad-hoc modules (no context-switching, it's just a hook), and we won' need to maintain specific documentation, 2) It will be much easier to transplant module management concept from Drupal core (e.g. dependency checking).

But, again, I haven't checked adrians patch in detail, so maybe we're there already.

As for the README.txt and branch housekeeping, I'll do that, once the dust settles.

Along with grugnog2's #334596: Improve root and uri detection logic and messages in drush.php, this is getting really exciting.

Last, I have opened #336269: Loading and merging multiple drushrc.php files according to sensible rules to scratch another itch that would play very nice with the "--include" part of adrians patch. Unless you beat me to it, I'll have a patch in there shortly.

adrian’s picture

I really don't think allowing the drush_command hook be in multiple places is all that useful, especially since you would be in situations where you could want the code to be in multiple places, which would result in namespace conflicts.

And drush.inc files would be similar in nature to .install functions. IE: they could still be loaded from modules when needed, but wouldn't need to always be present.

Owen Barton’s picture

So just to come up with a more solid example for us to get out heads around, lets think about coder module. This module has a pretty significant amount of code to do it's job, and most of it gets called from both the web interface and the drush command (and you would often want both interfaces available).

My understanding then is that you would copy coder.drush.inc from the modules folder into your drush folder or set up a drushrc for that site to include it. coder.drush.inc would then need some kind of check to see if the module was enabled before returning it's commands to drush.

I think that overall (if I have captured the workflow) this looks pretty good, although still raises a couple of questions.

I think it could be worth modules like these discouraging copying the file into the drush folder - that could cause problems because the drush module would still be per-site (because the user wants the web interface) and so if you upgrade one of your sites to a new coder version that changes the API then you have to either use that verisons coder.drush.inc (breaking when you use it on the old sites), or the old one (breaking on the new). Instead I guess part of the Drush installation would be to add an include parameter to the drushrc for that site, to include the coder.drush.inc for that site specifically.

Allowing modules to provide commands directly would avoid that step of updating each sites drushrc to include commands for each of the modules used on each site. I think that if you have a lot of sites and modules this could rapidly become tedious. One way around this (and perhaps this is what Adrian is suggesting) is for Drush (post full-bootstrap) to check each active module directory and auto-load a modulename.drush.inc file if it exists. How does this sound?

adrian’s picture

Oh. and when i mentioned the bootstrap stuff i made this the basis of, it also allows us to write a replacement for update.php.

adrian’s picture

My understanding then is that you would copy coder.drush.inc from the modules folder into your drush folder or set up a drushrc for that site to include it. coder.drush.inc would then need some kind of check to see if the module was enabled before returning it's commands to drush.

There would be no copying involved.

Drush would find all .drush.inc files available to the site (through the same method drupal uses to find modules to begin with).
The --include would be added to the end of this set of search directories.

Allowing modules to provide commands directly would avoid that step of updating each sites drushrc to include commands for each of the modules used on each site. I think that if you have a lot of sites and modules this could rapidly become tedious. One way around this (and perhaps this is what Adrian is suggesting) is for Drush (post full-bootstrap) to check each active module directory and auto-load a modulename.drush.inc file if it exists. How does this sound?

Yes. They would provide commands directly. The commands would just be stored in a modulename.drush.inc , not in the .module itself.

The drush_command hook would also be able to specify dependencies (ie: module x needs to be enabled for this command to be available).

And the commands would be able to specify which runlevel they execute on. IE: site installs and updates would run at DRUPAL_BOOTSTRAP_CONFIGURATION, and are thus available even when a site hasn't been selected.

Owen Barton’s picture

Sounds perfect :)

vingborg’s picture

And the commands would be able to specify which runlevel they execute on. IE: site installs and updates would run at DRUPAL_BOOTSTRAP_CONFIGURATION, and are thus available even when a site hasn't been selected.

adrian, that and install.php-as-a-drush-command was one of my primary motivations for starting to look into this. Is it something you have been working at? It rightly belongs to an issue all by itself, but what thoughts do you have on the matter?

adrian’s picture

Vingborg: I am the lead developer of the Aegir hosting system http://groups.drupal.org/aegir.

The system has 2 components, hosting (the front end) and provision (the back end). The back end can be run separately, and provides drush commands to install new sites (including generating virtual hosts and creating databases and soon nameserver provisioning), and many other things. It also fully supports install profiles and locales.

The front end provides a drupal based interface for managing these sites. Each action on the hosting interface, generates a task, which then gets mapped to a drush command on the correct platform (drupal release).

Currently we need to have a site with the provision module installed and enabled on each of the platforms, to be able to run it. I would prefer to have one provision module installed per server, and only have the provision_drupal module for each release used.

This is the major requirement of our second release (0.2). The third release will be doing all this across multiple servers through ssh tunnels.

I have many features bolted on to drush that I would like to move upstream for our next release (flexible error reporting and logging, a scripting layer for writing drush commands that are called by other drush commands and more).

If you'd like to chat sometime, you can find me on #hm2 on irc.freenode.net. I am Vertice.

vingborg’s picture

Here is a consolidated patch against DRUPAL-6--1 as of a few minutes ago.

It has the following highlights:

  • All of adrians extras, including module.inc.
  • It also enlists commands from "traditional" modules if Drupal got bootstrapped. This is not the full version that adrian wrote about, but it works if those modules are installed.
  • The README.txt has been updated to reflect the changes.

Known issues:

  • The simpletest commands only works if the SimpleTest module is enabled on a site. Right now, drush bombs out if you try any of the test commands.
  • drush spits out "install.php" html and exits if you invoke it on an empty site. I've not studied this, but I reckon install.php is doing something to circumvent the registered shutdown function.

I have started to work on the HEAD version of this patch, but I'm not quite there yet. And by the way, is there a naming convention for patches?

moshe weitzman’s picture

Great. A few more requests

- Add docs for module.inc. I can just see developers looking at this and puking all over their keyboards. It is usually a fatal mistake to maintain copies of core functions in your module. We need to explain why we need our own module system.
- Add brief API docs to README so that a module developer knows how to provide command(s).

I will test this out tomorrow.

moshe weitzman’s picture

Also, I'd like to go all the way and remove the whole /drush_sql directory and just have an /includes/drush_sql.drush.inc (for example). that file should get recognized by the drush module automatically. it would scan the root and /includes directories of all modules for *.drush.inc. this is how views does it ... we'll need some way to provide the hook_help texts from within the include.

vingborg’s picture

Assigned: Unassigned » vingborg

I experimented a bit with hook_help, and it turns out that all we need is to move the help hooks into the *.drush.inc files and use drush_module_invoke_all when calling for help (drush_callback_help was using module_invoke_all). There and back again, so to speak, since that means that the content of the *.drush.inc files becomes virtually identical to the original *.module files.

I have a few questions for consideration:

  • Should we simply call the drush command files *.drush or maybe *.command or should we stick with "*.drush.inc"? I think this is important since we're going to be stuck with whatever we decide for quite some time.
  • I was thinking about creating a "commands" folder along moshe's latest suggestion and an "includes" folder for all the drush "core" stuff. Any thoughts on that?

I'm still working on the latest round of suggestions and on the patch for HEAD, but It's probably not ready for review until sometime this weekend. It's going to be a couple of awfully big patches with a lot of untested behaviour, so I hope you guys will give it a good go.

Also, I have assigned this issue to myself. I hope you don't mind.

moshe weitzman’s picture

I want drush to be a model for all other modules in terms of how it ships its own commands. thats why i would like to follow the standard set by views, cck, og, and others. so, we ship with a folder called 'includes' and in there we ship with files called sql.drush.inc, pm.drush.inc, tools.drush.inc, etc. this file naming convention comes form module_load_include() so lets stick to it.

thanks for working on this.

vingborg’s picture

Ok, that took a bit longer than anticipated, but here goes a new version incorporating most (all?) of the recent proposals, and as promised it's a BIG patch. I've included both a clean patch against DRUPAL-6--1 and a ready-to-run version for convenient testing. You can simply extract the latter to any convenient location and point an alias to drush.php (as before) and then ... well, jump to a Drupal site to give it a go.

Included in this version:

  • A new "command module" structure, following the suggestions of adrian and moshe (all standard commands have been moved to the includes folder)
  • Implementation of "drush_help" hook in the new structure
  • drush also looks for commands in a .drush folder in your HOME directory, if it's there
  • An updated and extended README.txt (including a new "COMMANDS" section)
  • An barebones example drush command module (example.drush.inc)
  • An updated example.drushrc.php
  • Some extra commenting in various places

A few notes:

Since this version of drush now works independently of Drupal, the issue of compatibility across major versions (of Drupal) becomes very important. I can't quite decide whether I think that's an opportunity or a liability since there are solid use cases for and against decoupling drush entirely in that regard. Many aspects of Drupal are highly unlikely to change in ways relevant to drush. I tend to favor decoupling drush completely, but I haven't considered the issue in detail. As of now, if you strip out version specific commands, what's left is the entire framework and a fair bunch of commands that work exactly the same on Drupal 5, 6 and 7 (e.g. "drush cron").

In any case, we need to have a drush_drupal_version() detector and we need to put in some dependency management on the command level, as adrian suggested. Any ideas on that issue?

moshe: as for drush itself as an example for others, I quite agree, but I think we should hold the verdict on the exact template. I see what you're aiming at, but I think module_load_include() and module_load_all_includes() solves a slightly different problem. Also, I would prefer a cleaner cut between drush commands and other module code. I have a few ideas on the matter, but they are still a bit sketchy.

Finally, I don't think I'll work on the port to HEAD until we reach a fairly stable DRUPAL-6--1 version (or would that be DRUPAL-6--2?), but when that happens, I'll gladly commit to it.

moshe weitzman’s picture

Status: Needs work » Needs review

I tested the 'ready to run' version and it is working flawlessly. Code review revealed minor nits which we can resolve later.

My only major question is our pervasive use of the word and the concept 'drush module'. One code comment illustrates the problem - "A drush module is a file that matches *.drush.inc". Huh? Lets call such a file a drush command file (feel free to propose alternatives). I'm not sure why vingborg wants to distinguish these from standard drupal code, but I am OK with calling these files 'sql.drush' (for example). That would be a happy return to v1 of this module (see http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/drush/servi...).

Also, consider that drush_module_list() scans for modules that end in drush.inc (or .drush is we go with my suggestion above). Perhaps we are doing ourselves a disservice by calling this file module.inc and re-using the module terminology. what about command.inc and command_list(), command_hook(), command_implements(), etc. Sorry vingborg - I know thats a royal pain in the neck. Lets discuss.

Adrian mentioned that there should not be multiple ways to provide commands and I sort of agree. That means that we should stop looking for commands in module files. We only consider *.drush files. I'm open for discussion on this.

It is interesting to consider that drush could work across drupal major versions, but ultimately i don't think we can take much advantage of it. We are committed to distributing this project on drupal.org which means we must conform to its CVS branches and module download pages. So I think we will just release this project in lockstep with drupal major versions as we always have.

Thanks for this great patch, vingborg.

mikl’s picture

I don't think that a new file extension is a great idea, I consider PHP and Drupals cluttering of the filename namespace excessive already – I have like half a dosen extentions set up to match PHP in my IDE.

I prefer name.drush.php, but name.drush.inc is also okay

Steve Dondley’s picture

How difficult would it be to write a patch to backport this to d5?

adrian’s picture

That's one of the primary reasons i didn't add another .drush extension (although i think it would be cleaner, personally).

*.php to me means it should be executable on it's own, i guess. (but then, i did create the *.tpl.php convention, so i'm on pretty shaky ground arguing for that :) )

Oh. and how about splitting off the stuff that requires specific drupal versions into different projects, and keeping the core drush in a state where all the branches are exact copies of each other? (ie: tag off head). There's nothing in any guideline i know of that forces people to write modules that aren't backwards (or forwards) compatible, or to be able to use them without actually having a drupal install.

That is something that can be pretty easily documented.

vingborg’s picture

Steve Dondley:

How difficult would it be to write a patch to backport this to d5?

Not terribly difficult, as implied in an earlier post. In fact, preliminary (and very cautious) testing have shown that you can use the ready-to-run-version to write commands for Drupal 5, 6 and 7 with no obvious problems. For the time being, though, I strongly advice against doing that unless you are an experienced Drupal module writer and you have your backups in working order.

Let me repeat that, for public record: This patch (and the ready-to-run-version) is experimental, beta, untested and not to be trusted anywhere near a production site!

The crux of the matter is, that while this version now operates independently of Drupal, the commands that ship with it may use features that depends on specific major versions of Drupal. Some might even depend on other contributed Drupal modules. With luck, drush will simply crash, but things can get messy in unpredictable ways.

Having said all that, I'll probably do at least a partial backport to D5, since I still have a bunch of sites to maintain on that platform. That won't happen until the dust settles on the D6 and D7 branches, though.

vingborg’s picture

moshe (#28):

I'm not comfortable with the potential for confusion, either. I'll go with "drush command file", that sounds about right.

Using "command" in the code is also better, IMO, so I'll just go and do that. I think I'll prepend it with "drush_", though, to keep up with proper Drupal namespacing and all. So it will be drush_command_list() etc. in the next patch, I reckon.

moshe, adrian:

Yeah, a single point of entry for drush commands. I'll remove the scan for commands in Drupal modules. If a module writer wants to add drush support, it's as simple as adding a drush command file and start writing. A clean cut, and modules won't be burdened with the extra code in web mode.

Also, I was thinking about adding a "commands" folder convention for modules providing extensive drush support. Drush itself would use that instead of "includes". How does that sound? One could even have a "commands" folder in "sites/example.com" and "sites/all", along with "modules" and "themes"?

adrian, moshe, mikl:

"*.drush" or "*.drush.inc"? Both makes sense from different perspectives, and I'm kind of indifferent. I think I'll keep with the "*.drush.inc" pattern for now. Codewise, it's an easy fix, so we can change it later, if it feels better. Drush could support both, but that's probably not a good idea.

vingborg’s picture

adrian (#31):

Oh. and how about splitting off the stuff that requires specific drupal versions into different projects, and keeping the core drush in a state where all the branches are exact copies of each other? (ie: tag off head). There's nothing in any guideline i know of that forces people to write modules that aren't backwards (or forwards) compatible, or to be able to use them without actually having a drupal install.

Yeah, I was thinking along the same line. See my post above (#32), it was written at about the same time :-)

I can't comment on the wider issue of keeping several contribs in lockstep with each other and with Drupal core, as I'm still very new to this community. You guys will have to decide on that.

Drush will still need some dependency management at the command level. That shouldn't be too hard, if I can figure out a "drush_drupal_version" function that works reliably even before the Drupal bootstrap sequence. Maybe it could take a peek at the node.info file? That ought to work.

moshe weitzman’s picture

Oh. and how about splitting off the stuff that requires specific drupal versions into different projects, and keeping the core drush in a state where all the branches are exact copies of each other? (ie: tag off head). There's nothing in any guideline i know of that forces people to write modules that aren't backwards (or forwards) compatible, or to be able to use them without actually having a drupal install.

Thats a tempting proposal. Yet, I think almost all drush commands have changed over the d5-d7 span. Certainly drush_pm, drush_sql, drush_simpletest, watchdog vary across versions ... So we'd ship with a drush that could run cron and thats about it ... It would be interesting to ship with a command that could download the version specific commands for you. It would be a baby version of drush_pm.

@vingborg - drush_command_list() sounds good. personally i think *.drush files a /commands subdir is really clean. but for now i'm ok with sticking with *.drush.inc and /includes folder since thats what vingborg has.

vingborg’s picture

Hereby the latest revision, in ready-to-run format. I think the overall code structure is more or less in place now, but there are still a few cliff hangers.

I've not included a regular patch file this time, but I can provide one with little effort. I think this version is far beyond a mere patch, by now, so please advice on protocol in this matter.

Installation and usage is the same as the last version.

The notable highligths:

  • The 'commands' terminology is now implemented in code and docs. All command files reside in the commands folder.
  • I added an includes folder and moved drush.inc and command.inc in there.
  • I backported a few lines from HEAD, so that it now bootstraps Drupal 5, 6 and 7 without a hitch (I forgot those somewhere along the road).
  • It now correctly scans the current Drupal installation (if any) for command files.
  • Some sanity checks here and there, especially on the existence of directories.
  • A couple of functions for checking Drupal versions. This is the first step towards a dependency manager for commands (see below).
  • I added an extra command: 'status' (it's in drush.drush.inc). Currently it only reports the Drupal version of the current installation.
  • Various minor fixes, both in code and docs.

What's missing, still:

  • Dependency management on the command level regarding Drupal modules (e.g. Package Manager). I was thinking about adding some extra entries in the command descriptor array returned by the drush_command hooks, somewhat like what's in module *.info files. Adrian talked about something very much like that earlier.
  • Likewise, dependency management regarding drush commands.
  • Drupal version specific commands. Currently 'help', 'status', 'cron', 'eval' and 'cache clear' runs across all major Drupal versions and others may do as well. I'm still undecided as to the best way of doing that. moshe and adrian have thrown around some good ideas, but there is still no clear strategy. The actual grunt work should be pretty easy, but further discussion is needed, I think.
  • A marker for commands that doesn't require a fully bootstrapped Drupal site. More on that later, but essentially I'm thinking about diagnostic tools and overall site management. OTOH, it might be taking it too far, for now. Adrian, you seem to have thought a lot more about this, so please advise.
  • Some refactoring of drush.php. A lot of stuff should be moved somewhere into the new 'includes' folder, IMO. Some further breakup into separate *.inc files also seems prudent. Any suggestions?
  • Breaking README.txt into separate INSTALL.txt, USAGE.txt, COMMANDS.txt etc. BTW, are there any official guidelines for naming such files?

Oh, and this is the time to break out the nitpicker on code style, naming conventions etc. We might as well get this polished up good. I'm in The Zone on this project right now, so feel free :-)

adrian’s picture

A marker for commands that doesn't require a fully bootstrapped Drupal site. More on that later, but essentially I'm thinking about diagnostic tools and overall site management. OTOH, it might be taking it too far, for now. Adrian, you seem to have thought a lot more about this, so please advise.

I actually got this working previously.

I simply move the drush_bootstrap_drupal to the latest possible moment (after it's found it's command), and it was parameterized, so it would take the 'bootstrap' property of the command in drush_commands.

From that point onwards it's up to the drush command itself to manage the bootstrap level (if you look in install.php / update.php you will see what it does). If there isn't a bootstrap property, it simply did a DRUPAL_BOOTSTRAP_FULL.

There were a couple of tricks though :

  1. you would need to include bootstrap.inc first to be able to use the constants, but this could be worked around by adding our own mirrored set of DRUSH_BOOTSTRAP_X levels.
  2. you couldn't use t() on non bootstrapped commands, because that is only loaded when common.inc is loaded which is only at a specific bootstrap level.
    • This could potentially mean that you wouldn't be able to have one command.drush provide both BOOTSTRAP_CONFIGURATION and BOOTSTRAP_FULL commands, as alll the functions might not be available at lower levels.
    • You could also just rely on get_t() in your code, but that gets messy .. oooor you could just use st() in your code, which I think might be a sane solution for all drush commands to begin with (http://api.drupal.org/api/function/st/6)
  3. Perhaps a dt() function of our own would be better, as st() seems to be hardcoded for install profiles, and we would probably want to be able to provide translations for command help that aren't available elsewhere. How do normal shell applications handle this stuff?

It's probably at this point you would add the dependency check, and only if it has done a DRUPAL_BOOTSTRAP_FULL.
My idea on the dependency checking was very simple actually. Just have a 'requires' array property, and it would do :

   
   if (DRUSH_BOOTSTRAP_FULL) {
      $status = TRUE;
      foreach ($command['requires'] as $module) {
         $status = $status &&  module_exists($module);
      }
      if (!$status) {
          print("E: a required module could not be found");
      }
   }

I wasn't even going to think about dependencies between 'drush command files'

vingborg’s picture

@adrian, on bootstrapping:

I simply move the drush_bootstrap_drupal to the latest possible moment (after it's found it's command), and it was parameterized, so it would take the 'bootstrap' property of the command in drush_commands.

That sounds better, no matter what, and I will incorporate it in the next revision. I will also add a level property to the command descriptor, which can have one of the following values:

  • system for commands that work purely on the drush level (i.e. we didn't find a Drupal anywhere). Currently, that's the help and status commands, only.
  • project for commands that requires a Drupal root installation (but not necessarily a working site).
  • site for commands that requires a working site. This is the default.

How does that sound?

Then, somewhere down the road, we may consider adding (or leveraging) a Drupal bootstrap API, possibly with relevant hooks and stuff. But with the above, I think adrians kind of use cases (Aegir) would be covered nicely, at least for now.

The issue of t() has caused me some trouble. First and foremost, I'm not sure anybody would care enough to actually add translations, since drush is not that kind of tool. I know that I wouldn't. I'm not a native english speaker, but, frankly, the very thought of having my shell barking at me in danish is ... disturbing. For better or worse, english is our professional language.

Second, the use of t() as a kind of low-key printf() could be covered by a few extra lines of code in drush_print(), since it's only a loop with calls to strtr() ... it would barely even qualify as code duplication. Only the !placeholder format makes sense on the command line, anyway. So, instead of the drush_print(t('some !strings', array('!strings' => 'things'))) it would be drush_print('some !strings', array('!strings' => 'things')). If we really wan't to provide a generic translation mechanism, we could base it on plain, old gettext and put it in drush_print() and it's ilk.

Third, commands that really does need t(), would always be site-level, so the t() would be jacked up and good to go.

moshe weitzman’s picture

Thanks for this improved version.

I'm waffling a bit on the commands folder. I like it in Drush, but thats about the only module that needs multiple *.drush.inc files. Most others will be coder.drush.inc or whatever. It would be more convenient for other modules to put *.drush.inc into its module root directory or a /includes subdirectory. So, could we please add those locations to the search path and update the docs? I'm willing to get rid of the commands folder and package ours in includes as well. Sorry for my indecision here.

I don't think it is feasible to keep one codebase across drupal versions. I don't like the idea of creating a separate version-specific project. So lets keep on distributing this as a full package, with all the command files.

Personally, I like a single README.txt file.

I'm willing to defer the dependency and bootstrap improvements that adrian discusses. Or Vingborg can tackle them now if he wants.

adrian’s picture

Third, commands that really does need t(), would always be site-level, so the t() would be jacked up and good to go.

The issue is that you can't even include .drush files that have t() if you don't have a bootstrapped site, as it will end with a php error.

I do think we can also handle the bootstrap stuff in a separate patch (which is where the t() issue comes in). but I'm growing on the idea of using a separate dt() function, which can look at the $LOCALE environment variable, which is the correct way to handle shell based translations.

Commands wouldn't be translated, only messages / help text.

Also, i've never liked the drush_print function, fwiw. I built a mechanism closer to drupal's output system that could use theme().

mlncn’s picture

I love the concept! This is huge for Drush and moving toward modular, community-standard practices for rapidly deploying Drupal. I played the role of bumbling tester, notes at Agaric, because I do that well.

In short I can confirm that that it works for our main use, drush pm (installing and updating modules with package manager), now from outside of anything Drupal.

Are there project-level commands I should test with a site that isn't running?

benjamin, Agaric Design Collective

vingborg’s picture

@Benjamin: thank you for testing this. I would like to hear more about this Mac OS X problem you mention, as it has cropped up under various guises before. It would be nice to have that sort of stuff covered, since out-of-the-box usability, for my part, is a primary design goal of this version. At the very least, drush should always return some usable hints about what might have gone wrong, but I suspect that's not quite possible with the currently supported Drupal versions. I don't use a Mac myself and rarely venture into Windowsland, so detailed feedback is needed on platform issues.

The issue about an existing Drush module is hopefully transitory, but should certainly be mentioned in the README or something.

As for the project-level commands, both the concept and the name is still in the works, so you'll have to wait a bit.

Oh, and about that tarball: a goof, plain and simple. Won't happen again.

vingborg’s picture

@moshe (#39): I agree with that. A 'commands' folder is overkill in the vast majority of cases. I just checked the code, and right now it actually doesn't enforce any such thing. It simply adds the current Drupal root to the search path. Thinking about it, it should probably only check the 'sites/all' folder and the current site folder, and watch out for duplicates. As it stands, a 'commands' folder for modules is merely convention.

I have another reason for keeping the shipped commands separate from the rest of drush: right now, the only difference between between a D5, D6 and D7 "official" version would be some of the files in the 'commands' folder. In my book that's A Good Thing, since 1) I doubt the D7 bootstrap sequence will change significantly in ways relevant to drush and 2) I have publicly committed myself to porting this version back and forth. Less grunt work on several levels :-D

On a more general note: While we should certainly maintain ready-to-run packages with all the trimmings for currently supported Drupal versions, we should not, IMO, hide the fact that the drush framework is inherently independent of Drupal version. In fact, I think we should actively pursue that aspect. It will greatly reduce future maintenance.

So, how could we possibly fit a "bare-bones" version into the repository?

Anyway, I'm getting talkative. I will fiddle with the latest round of feedback and publish a revision sometime tomorrow night (CET). Then I will go about porting the command files to HEAD and D5 to the extent possible.

vingborg’s picture

@adrian (#40):

The issue is that you can't even include .drush files that have t() if you don't have a bootstrapped site, as it will end with a php error.

Are you sure about that? I think that the parser will handle it fine, but that the runtime engine will issue a fatal error, if you actually try to execute the function. Must check up on that.

On the issues of bootstrapping and localization in general, I don't think I will work more on those for the time being. Better to focus on getting things settled overall. Localization is a nice-to-have, but not essential and detailed bootstrap control probably deserves more consideration. So let's resume this discussion later. It is certainly interesting.

moshe weitzman’s picture

Will this discover *.drush.inc files that belong to inactive modues? If so, thats pretty disconcerting. This could be fixed with dependencies as adrian suggested. is that the best way?

vingborg’s picture

@moshe (#45): yes, right now it will. I'm aware of the problem (and I agree, it is a problem). Dependencies will be a part of the solution, as well as moving some other code around a bit.

moshe weitzman’s picture

For limiting drush commands to active files, you might have a look at simpletest_get_all_tests(). See http://api.drupal.org/api/function/simpletest_get_all_tests/7

Also, I forgot to mention that core has a VERSION constant at top of system.module. No need to look at node.info

Owen Barton’s picture

I just took a shot at this - now commands can pass an additional 'bootstrap' array element, and drush will only bootstrap to that level. I have moved the inclusion of bootstrap.php a bit earlier so we can use the regular constants. It defaults to DRUPAL_BOOTSTRAP_FULL, which is needed (AFAICS) for most of the core commands. I have also added a new DRUSH_DRUPAL_PRE_BOOTSTRAP, which prevents any bootstrap at all (even a valid configuration).

I also changed how drush_shutdown() works, because detecting a function in common.inc is not a sign of success in other bootstrap levels. Instead we simply set a global to indicate that we have come out of bootstrap successfully, and suppress the message.

I also added an (incomplete) dt() function and replaced some of the early t() calls with this (should probably do the others too). We should figure out what approach we want to use for this, and we can use this as a simple wrapper function.

Owen Barton’s picture

I think that once we have cleaned this up a touch more, and made sure that the .drush.inc approach is the right one we should probably just commit this as a 2.x branch, which will allow us to work on this in more sensibly sized patches :)

vingborg’s picture

@Grugnog2 (#48):

That's interesting, and it seems to work fine. I have a couple of questions, though:

First, does this require a valid Drupal installation? That's not guaranteed anymore. Wouldn't drush need to load 'bootstrap.inc' before the drush_command hooks was executed?

Second, does this tie drush to specific Drupal version? That issue is still up for grabs, but I would very much like the drush framework to remain that way. Are the DRUPAL_BOOTSTRAP_* constants officially documented or are they internal to Drupal core? Are they stable across major Drupal versions?

At the end of the day, we'll need real commands that actually uses this feature, so as to get an idea about how it pans out. Adrian seems to have some ideas up his sleeve, so perhaps he will put it to a test somehow?

I will certainly take a closer look at this, but I will also take a stab at the concept I outlined in #38. The two can easily coexist, and the 'level' setting would cater for the majority of cases.

On the drush_shutdown patch: yes, that's more sensible, regardless of the bootstrap method.

On dt(): Yup. We could eventually work gettext into that.

adrian’s picture

I'm committed to making drush be version agnostic, if that means I need to fork it, so be it.

It's either that or write my own drush like tool and stop using drush entirely (which i was going to heavily consider for the next release of aegir had this patch not appeared).

moshe weitzman’s picture

OK, Sounds like there is strong interest in keeping drush version agnostic. I guess we would move most commands to a Drush commands project? Could we ship core drush with a command which will install the right version of this project? Is there some way to put pm install into the core distro? Thats probably wishful thinking. Anyone have a vision for this?

I agree that this needs a little more polishing and then we'll commit. I guess I would create a 7.x branch, and then put all the new files into HEAD. Is there some easy way to do all the adds and deletes? I'm thinking of what svn_load_dirs.pl does for SVN.

Owen Barton’s picture

@adrian - the version dependency was an oversight on my part - not intended to be a design decision! Let's switch it out with something not dependent on bootstrap.php.

adrian’s picture

We can still ship everything with the core distro, but version specific ones will replace the core shipped ones when it loads a specific uri.

We will always need to ship a set of version specific commands, but the way that provision (the aegir backend is written), only the commands that actually need to load the site's db (install, update etc) will require a platform to work on. The rest will be stored outside.

I've just started working on merging the code bases for all the different revisions again, but what this will eventually mean, is you will only
need to update 1 module to support a new drupal release.

I spent last night breaking out the install stuff from drush, into it's own .php (that has an include that simulates some drush things) :
http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/provision/p...

That will take an already configured settings.php and created db, and install drupal on it (with the parameters).

I use my scripting and logging layer for it, so anything changed / logged during the separate .php process gets merged into the final output.

That install.php file could be turned into a bootstrapless drush command pretty simply. I want to hack up an update.php using a similar method soon.

vingborg’s picture

Well, I got sidetracked by invoicable activities, so I couldn't make up on my commitment almost a week ago. Sorry about that. I have a patch ready, though, that just about covers all of it so far, including the issues covered by the latest release (6.x-1-2, 5.x-1.4) and a few other things. More on that later, as I would like to include a transform of the version specific standard commands, as well.

@moshe (#52):

Is there some way to put pm install into the core distro? Thats probably wishful thinking. Anyone have a vision for this?

As far as I can tell, pm hinges on a single version specific feature of Drupal, namely the update XML parser. All the rest is either backport issues or very minor details. It really should be possible to extract a generic version of that code, since I doubt the actual format has changed very much. That, of course, would amount to bona fide code duplication, but it just might be worth it.

Is there some easy way to do all the [CVS] adds and deletes?

I could work up a one-time little shell script that handles the details on a POSIX system.

@adrian (#54):
That's a very nice pile of code, there. Right now it seems very Drupal 5/6 specific, but I suppose that's priorities at work :-)

And, please, oh please, keep us posted on your drushification of install.php and update.php,

On the general issue of version specific commands, there might be a different option, namely to work up a scheme for supplying version specific include files, or just switch (drush_drupal_major_version()) { ... } directly in the commands for simple cases.

If we really ship drush with it's own "command package manager", that would be preferable, but the issue of version agnosticism still needs some work on the command level. I, for instance, am actively working on D5 and D6 projects and I dabble a bit with D7, so I would feel the heat with most "naive" implementations.

In any case, it is a notoriously difficult issue, and we should take care not to create our own, little version of DLL Hell.

Frando’s picture

This issue looks very promising indeed. Great to see more people work on drush.

Regarding version agnostic vs. version specific, I'd propose to do the following:

In the drush directory in CVS, we create two subdirectories, e.g. named drush_core and drush_commands. drush_core would be the same across all CVS branches, containing drush.php, drush.inc and all commands that can be completely version agnostic. Everything in the drush_commands directory can be major version specific, i.e. differ between the branches.

The drush_core directory can also be moved completely out of the Drupal directory and be placed anywhere.

Whenever a command is invoked, the rule would be to check if a version specific implementation is available (i.e. a command implementation located with the site for which drush was invoked) and if not fall back to the version agnostic one (i.e. a command located with the drush.php that was executed), should it be there.

Making drush_pm completely version agnostic would involve quite some copypasting, as it relies on update_status.module/D5 resp update.module/D6. So to make it version agnostic we would most likely have to copy the xml and info file parser from update.module, which would be quite some code to maintain. An alternative could be to have a very limited and basic drush_pm in the version agnostic part of drush that basically can do nothing but install the most recent package of drush into the currently selected site (matching the major version of the selected site, thus then installing the matching version specific parts). So no info file parsing or update functionality would be needed, only parsing one xml file. As soon as the version specific drush is installed for a site, the full range of commands becomes available.

moshe weitzman’s picture

Thanks Frando.

What do others think about his suggestion to have two top level directories? One reason not to like it is that it differs from how Contrib and modules will supply commands. Is it important to be a model? Splitting drush into a 'Drush extras' at least prevents us from being a bad model. Just fishing for opinions here.

Yes, that very minimalist pm install is what I had in mind.

adrian’s picture

I'm starting to think we really need to have this patch land in some form so we can collaboratively work on it. It's simply grown far too large to manage solely in the patch queue.

Basically, we should create a DRUPAL-7--1 branch for what's in HEAD now, and apply a somewhat working version into HEAD that we can refine further and make DRUPAL-x--2 branches from once we've sorted out the issues.

For this we need to at least get the file layout right, so we're not constantly moving files about.

adrian’s picture

I just spent a few hours refactoring a local checkout of provision, in preparation for our 0.2 branch (which will depend on this patch),
I fixed most of the smaller issues i came across when trying to test this with the patch before.

so I should have a substantial code base to test all the edge cases of this soon (think: installing drupal from the command line, updating sites, making backups and restoring them, changing db servers, provisioning mysql user accounts and apache virtual hosts, and much more).

I also wrote a script to run update_x functions for d5/d6 (part of our 0.2 milestone), and there's some other interesting bits and pieces i want to play with such as using drush to actually check out a whole drupal tarball, download just the version specifics drush bits and install them, and then offering them up to you. I also want to try and make it so drush can be run on any platform you point it at, and it will initialize all the version specific bits for you.

I'm going to try and get as much of the extra provision stuff I have written into drush too, such as flexible logging and error handling, with the ability to run drush scripts and integrate the output of the commands (think update all sites on a platform, where every specific site's update command runs in it's own php process).

vingborg’s picture

At last, I got the stuff done. Attached to this post is my latest attempt at a version agnostic, stand-alone drush along with a first stab at porting the command files from DRUPAL-5 and HEAD.

It's not quite a complete rewrite, but it's certainly a major refactoring/rearrangement of my last version along with all the bits and pieces that came up along the way. Drush-the-framework is now in state that's as stable as makes sense right now.

Highlights in this version:

  • As mentioned, a lot of refactoring, ironing out oddities, stratifying naming conventions and a few extra include files.
  • A lot of commenting along the way.
  • Improved environment detection, such as dealing smartly with missing Drupal installations, missing sites, detecting sites in subfolders and more.
  • Loading and merging of multiple configuration files #336269: Loading and merging multiple drushrc.php files according to sensible rules.
  • Help command is now integral to the framework, so the drush.drush.inc file is dead.
  • Prepared for dependency checking on command level along Drupal version, Drupal modules and drush command files (see drush_parse_command()).
  • Support for bootstrap setting on commands.
  • Support for scope (system, project, site) on commands -- it still needs to be implemented, so maybe it's YAGNI.
  • A preliminary dt() function -- but still no independent i18n support. It uses t() if present.

What's missing: Mostly dependency and scope management. And lot's of real-world testing ;-)

The command files for Drupal 6 are included in the big tar-ball.

I have started on porting command files from the other branches. They are also attached to this post in separate tar-balls. If you care to dig into them, they are not unmanagably different. Many commands differ only little and the pm handlers (wget, cvs, svn) were completely identical, so I have not included those. I think that with a little further work, we can get this down to a very maintainable size. Right now you'll have to setup shop by yourself in order to get it to work, since many functions have the same names, but I'm sure you can manage ;-)

We are still left with the question of how to deal with the actual packaging, but at least the basic porting is done. I have only tested superficially, so issues may yet arise.

I have also attached a couple of interesting extra command files for the heck of it. You can drop them in your ~/.drush folder for now, and simply try them out. The "script" command is rather interesting, I think. The 'status' command is mostly for testing, but it shows one way of dealing with the cross-version issue, at least for the simpler cases.

Hmmm ... I think that's about it for now.

I fully agree with the sentiment that this should go to HEAD as soon as possible.

moshe weitzman’s picture

Status: Needs review » Fixed

Committed this terrific work to HEAD. I moved a few commands into a new includes/core_commands.drush.inc. Below are some notes from my testing. We should investigate and patch these if possible.

Note that I did nothing with the D5 and D7 code that was posted. Lets deal with those branches once the dust settles.

I have not yet created the drush extras project to hold the remaining commands. I am thinking that I will do with a tiny .info and .module fie since many people will want to deploy the commands as modules so that the code is in a well known place for their whole dev team. agreed?

---------------

1. When passing --root, I have to pass an absolute path. If I use a path containing '~' such as ~/htd/pr6, I get a chdir error. Any idea why that is? Could we avoid that?

2. Lets give an error msg if file is not found in 'script' command ... Please add instructions about --root if 'No Drupal installation was found.' in status command ... The command declaration uses 'level' instead of 'scope'.

3. At some later date, we should get rid of globals like $GLOBALS['args'], $GLOBALS['override']

4. command.inc: We search for command files in all directories of all active modules. I think we should actually limit the searching to the 'commands' and 'includes' and root directories. I am worried that some modules ship with thousands of files and we will needlessly scan them all. Perhaps thats excessive caution?

5. With standalone drush, we list all available commands but you can't get Help on most of them unless you specify a site root. Seems incorrect to me. Lets fix that if not much special case code is needed.

6. We should merge the 'eval' and 'script' commands such that eval is an option on script (i think).

7. We really need to implement checking for 'scope' (i.e. site, system, ..). The core 'cron' command that I have added fails ugly when you don't specify a site.

8. I had a strange error when i defined the 'status' callback in both my home folder and in drush core. the error:
Warning: call_user_func_array(): First argument is expected to be a valid callback, 'core_commands_status::status_callback_status' was given in /Users/mw/contributions/modules/drush/includes/drush.inc on line 31. Ideally drush would just pick one command that is authoritative and use it.

moshe weitzman’s picture

Priority: Normal » Critical

It seems that modules can no longer provide drush command files because we fail the bootstapped condition in drush_commandfile_list(). Lets fix this fast. I am just finishing up drush_extras project but it will be not so useful until we fix this.

moshe weitzman’s picture

I have committed the pm, sql, tools commands into the new drush_extras project - see http://drupal.org/project/drush_extras. The committers for drush have commit access on Extras as well. I hope folks will subscribe to the issue queue there.

We need to work on the pm commands since we were expecting folks to only enable pm_cvs and pm_svn if they needed them but now they are always available from the perspective of help text. But their code is not available like it was with the module system? Perhaps Grugnog2 can look into this?

vingborg’s picture

@moshe, #61:

This is great! It's almost official :-D

I am thinking that I will do with a tiny .info and .module file since many people will want to deploy the commands as modules so that the code is in a well known place for their whole dev team. agreed?

I can see no reason not to do that. A free and straightforward courtesy. Come to think of it, is the .module file actually needed?

When passing --root, I have to pass an absolute path. If I use a path containing '~' such as ~/htd/pr6, I get a chdir error. Any idea why that is? Could we avoid that?

I was a bit baffled by this, at first, but then it occured to me that '~' expansion is actually a feature of bash (and most of its *NIX shell siblings), not a Drush or even a PHP issue. If you use something like "drush -r ~/www/drupal6", it will work. It would be nice to cover all angles of this, though, and I reckon a patch would be 3 lines, at most.

I think we should actually limit the searching to the 'commands' and 'includes' and root directories ... Perhaps thats excessive caution?

I can't make up my mind on this. Since Drush will mostly run interactively -- or at least not in webserver space -- it might be a premature optimization. Then again, it might be prudent. In any case, I think the search rules for drush command files should be simple, intuitive and flexible. Easy to document, easy to follow and catering to both the casual and the advanced user.

We should merge the 'eval' and 'script' commands such that eval is an option on script

It might improve usability, but I see script and eval serving slightly different purposes, where 'eval' serves the very quick'n'dirty use case. Also, I have a number of improvements slated for 'eval' (some of them suggested elsewhere, by others) that would make it vastly more usable in its own right. Finally, I have an experimental "drush interactive" running that actually builds up from there, so if you can muster a little patience, I hope to show up with an "interesting" patch in the near future :-)

On the rest of your issues: Agreed, more or less. If no one else does, I'll give it a go very soon.

adrian’s picture

I think it would be useful if we got together on irc sometime to hash out some tickets for the way forward with drush.

That way we can at least plan which features need to be worked on, and get a general idea of the direction.

moshe weitzman’s picture

Everyone who matters has posted in this issue so I will announce here:

We will hold an IRC meeting about drush on Friday morning (USA). For your local time, see http://timeanddate.com/worldclock/meetingdetails.html?year=2008&month=12... .

Lets meet in #drupal-dev on freenode. If someone wants to create a dedicated room, we'll point each other there.

Lets discuss our visions and designs for the next generation of core and commands. Adrian will to share some of his code from the Aegir project.

moshe weitzman’s picture

Status: Fixed » Patch (to be ported)

Would be great if folks could port Drush Extras to HEAD. D5 is nice too, but less critical. See http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/drush_extras/

moshe weitzman’s picture

Status: Patch (to be ported) » Fixed

FYI, I took Vingborg's commands and branched drupal_extras for D6 and D5 in addition to HEAD. I made dev snapshot release nodes as well.

moshe weitzman’s picture

Reminder: the drush mtg begins in 30 minutes. See you in #drupal-dev on freenode

moshe weitzman’s picture

Version: 6.x-1.1 » 7.x-1.x-dev
Category: feature » bug
Status: Fixed » Active

Houston - we have a problem (a good read - check it out).

I cannot get drush_extras to load in HEAD. The problem is that the whole module_list() situation has changed in HEAD. We now use a code registry to load stuff on demand. I am not at all sure we can cleanly keep our goal of a version agnostic drush.

I encourage everyone to take a look and see what can be done. The actual failure point is the call to module_rebuild_cache() in /includes/command.inc but thats a symptom of a greater problem.

Be sure to cvs up on drush_extras since I have just added some needed bits for it to be enabled on the Modules page.

I really should have caught this before we committed. Ugh.

adrian’s picture

i thought we decided not to look at modules for drush_command functions, so there would be only one way to define them?

We should not be using any drupal core functions in drush at all, and where we are forced to we can maintain a set of wrapper functions. When a new drupal release is required, only these will need to be updated.

I think changing 1 file (maybe) with something like 5 functions (conf_path, module_invoke, and some others) once per major Drupal release, is a lot cleaner and faster than changing X files with Y functions Z times (where z = number of patches committed , y and x are the files and functions changed in each patch).

I'll even offer to maintain that file for us with every release, as I will need to make provision compatible with the latest Drupal version, so it would be my first port of call.

adrian’s picture

Status: Active » Fixed

I debugged this and found that nothing in the drupal api was changed enough for this not to work, and after some debugging i found the issue and wrote a patch.

The patch is here : http://drupal.org/node/349966

Making this fixed again (this should have been a different issue).

adrian’s picture

I debugged this and found that nothing in the drupal api was changed enough for this not to work, and after some debugging i found the issue and wrote a patch.

The patch is here : http://drupal.org/node/349966

Making this fixed again (this should have been a different issue).

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.