In some cases, its required that you "mame kittens" and modify a contrib, in these situations it would be very helpful if it were possible to exclude/ignore these modified modules / themes from the drush update script.

For us the ideal would be to check for a .drush-ignore file in the module/theme folder, but any solution would be brilliant.

(Apologies if this has been asked for already, i did some searches and couldn't find a similar request/issue).

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

moshe weitzman’s picture

Yeah, thats a reasonable request. Not currently possible AFAIK.

adrian’s picture

i think this could be a good feature for the drupal ports system, in the future. namely , the ability to 'lock' instances of packages.
it will also be able to detect modified packages.

What I would personally highly recommend:
Import your installation into a subversion repository.
When you need to update, don't use drush dl, but cvs update and then svn commit.
To roll out on server, just do an svn update.

If you need to manage modified versions of modules, doing so without the backing of a versioning system is dangerous and irresponsible.

Owen Barton’s picture

Note, that update_advanced has the ability to ignore updates on certain projects (as update_status did in 5.x). We should probably check that if we can, although a .drush-ignore would be good in addition, as would a hook to allow you to wire in your own patch management checks.

a_c_m’s picture

we use BZR instead of SVN but the idea is the same, we also keep a log and patch files for any changes we make, so we can re-apply them when we do want to update.

However, it would be nice to be able to use drush to still update all the other non modified modules.

Owen Barton’s picture

mlncn’s picture

Subscribing, this would be very useful, and we'd review patches. Need to get more into Drush before attempting to write the patch in the first place...

ben, Agaric

seanr’s picture

FileSize
1.09 KB

Figured this one out. I've attached a very simple patch to skip any module containing a .drush-ignore file. It will pass along the following warning (in this case I used imagefield as a test):

Module imagefield has been ignored. Remove the file ".drush-ignore" from the /www/drupal6.ngphost.com/html/sites/all/modules/imagefield directory to update this module. Note that doing so will overwrite any code customizations you have made.

After removing the file and running drush update again, the update proceeds as expected.

seanr’s picture

Status: Active » Needs review
moshe weitzman’s picture

Status: Needs review » Needs work

Hmmm. i would think we would want an array that is passed in like structure-tables and skip-tables. see example.drushrc.php

seanr’s picture

That would work as long as each site can have its own config, though I do like it being as easy as "touch sites/all/modules/modulename/.drush-ignore" rather than having to create a whole PHP file. Also, I'm having a hard time figuring out how those config options actually get referenced within Drush.

moshe weitzman’s picture

you can put a drushrc.php in each multisite. this is described at the top of example.drushrc.php. the options in this file are loaded very early in the drush request. fire up your friendly debugger and step through drush. its a great movie.

geek-merlin’s picture

subscribing, would like this too.
thank you sean for the solution-for-now!

xurizaemon’s picture

The use cases for drushrc restrictions on upgrades and the suggested .drush-ignore seem different.

In the case of a multisite install with a hacked module in sites/all/modules/mymodule, the .drush-ignore fix will allow easy protection of the hacked module for all sites.

To achieve the same end for a module in sites/all/modules, the .drushrc.php exclusion will need to be done in the Drupal installation root. (My preference is to keep the core Drupal codebase unchanged and make modifications only in sites/*, and using .drush-ignore will allow this where using drupal-x.xx/drushrc.php won't.)

If placed in sites/example.org/drushrc.php, update of another instance on the same multisite might affect a shared module unless the exclusion is added to all sites/*/drushrc.php

If placed in ~/.drushrc.php or Drush install folder, the exclusion would apply to all multisites on the server.

I don't disagree with Moshe's suggestion that we add an $options array to protect modules, but I would like to see support of both that and the .drush-ignore approach in Drush, because I think that .drush-ignore has a valid use case (simple preservation of hacked modules without need to maintain extra files in the Drupal install dir).

I can't see how that same result can be achieved via drushrc.php at present?

moshe weitzman’s picture

Anyone care to weigh in on how we add support for locking a version?

greg.1.anderson’s picture

We could support ignores via $options if we added sites/all/drushrc.php as a location where drush searches for config files.

I'm kind of partial to also having something akin to .drush.ignore, so that module-handling preferences would automatically travel from one installation to another, e.g. if you rsync a hacked module from one site to another, or if you check a hacked module into a repository and then checked it out on another site.

Ideally, the update options would allow you to choose one of four modes:

1. clean (the default)
2. ignore (do nothing)
3. patch (make a patchfile from the installed version and the new version and apply it to the hacked files)
4. preserve list of named subfolders / files (for fckeditor, etc.)

I've sort of been holding off on commenting on this for a while, though, as I wanted to experiment with checking my modules into a repository (since that apparently affects the upgrade process), and I also wanted to look into some of the related issues regarding automatically loading module dependencies (e.g. via drush make).

There is also the possibility that the hacked module might want to provide a hook to affect updates in a semi-automated manner (#604820: Drush system commands).

Just thoughts; I still have other things to get a handle on before going down this road.

Frando’s picture

I really like the .drush-ignore version. When I have to hack a contrib module for a site, it would be fantastic if I could just do cd sites/all/modules/views, hack away and then touch .drush-ignore and then continue keeping my other modules up to date with drush updatecode.
Another solution that would work well for me is adding a line to the info file of the hacked module, but I think a seperate file is the easiest.

Both of these would be much more usable in my usecase than having to add the hacked module names to a drushrc.php (even though that might have use cases of its own and could easily be added additionally). I'd like to keep the flag really simple and at the same place as the hacked code, so for example if then my hack is actually committed in the project and a new release is there, I can just "rm .drushignore" and "drush updatecode" and be done with it. Dead easy, isn't it?

Actually, I'd propose to call the flag-to-ignore file IS_HACKED, then it would be immediately visible when browsing through the code (very helpful when working on a site you haven't worked on for a while, of course your VCS commit logs also tell you which modules are hacked but in my experience that's much more time consuming then a quick find . -name IS_HACKED). Also, the IS_HACKED property might have other use cases beside drush, so there's no really a reason to call it .drush-ignore.

greg.1.anderson’s picture

If you just want to see what is hacked, take a look at the hacked module. It even comes with drush integration.

Right now I'm working on command hook stuff; I was thinking that perhaps I might submit a patch to the 'hacked' module to hook into updatecode dispatch to ignore hacked modules. Not sure that the separation is worth it.

xurizaemon’s picture

+1 Frando's suggestion IS_HACKED is probably clearer and less Drush-specific than .drush-ignore as a filename.

+11 Greg's suggestion of option 3,4, 'patch' and 'ignore subtree' for module update. Nice. (But let's get options 1,2 going first?)

The 'hacked!' module does look handy, but it doesn't seem like a solution for the use case I mention in #13, ie simple preservation of hacked modules across multisites without (a) need to maintain extra files in the Drupal install dir (b) specific configuration on each multisite site.

'Hacked!' module would presumably need to be enabled on each site of a multisite (or each that you might run drush update on). This adds module overhead, and means a newly enabled site without 'hacked!' enabled might blow away your hacked version. I wonder if it would also slow down the module update process by comparing each module with a pristine copy (speculating here on how that module works).

Also, the 'hacked!' module's description does say,

This is primarily a developer tool and should never ever (don't even think it) be installed on a production site.

Greg's comment did say "if you just want to see what is hacked", so I'm inclined to read it as a useful tip rather than a potential way of solving the issue under discussion here (but pls correct me if wrong).

moshe weitzman’s picture

ok, i'm fine with .drush-ignore file.

IS_HACKED is screaming, derogatory, and inaccurate. there are plenty of reasons one would skip update that have nothing to do with editing a file.

greg.1.anderson’s picture

re: #18, yes, that was just a side comment, but along the same lines, you should never update on a production site either. Update on a dev site, test, then sync back to the production site. I tend to think that some of the utility of hacked could be made available to drush updatecode even when the hacked module is not enabled. As Moshe mentions in #19, though, editing files is only one of the use cases under consideration, so hacked! certainly does not address everything.

anarcat’s picture

As adrian hinted at with the "ports" reference earlier, I'd like to mention that we'll eventually need a more general database of "packages" (installed, on hold, removed, purged are states in Debian's APT, to take an example). I think a toplevel drushrc.php (which is recognized by Drush out of the box) could be a good start, don't you think? :) Aegir stores this information in the drushrc.php and the database, although I'm not sure it does it fully in the drushrc.

I don't oppose a .drush-ignore file, but I think it's just a workaround for a more general fix, and should eventually be dropped. So I'd rather go the right way first, but I have no code or time to patch, so feel free to disregard.

I'd also mention how this could related to #691174: Allow drush command files to define functions that control whether or not they will be loaded in that we have an overlap in the way Drush needs to be made to ignore some stuff, whether it is for upgrades or loading.

xjm’s picture

Tracking. There are plenty of legitimate reasons a module might need to be skipped: perhaps a patch is required, or a new version introduces a bug, or a dev build includes a needed feature that isn't available in a release.

sagannotcarl’s picture

I fully agree with moshe in #19. A simple ignore file (or drushrc.php, I'll defer to other on the relative merits of each) makes a lot of sense.

Bobuido’s picture

I don't have any suggestions for the implementation but it sure would be good to exclude modules form the upgrade process

+1 The feature request

Thanks for all your hard work on Drush - It's a truly awesome tool

aleksey.tk’s picture

I'm also interested in this feature. It is really useful not only if you have hacked contrib, but if you want to fix the module version you use.

anarcat’s picture

Just a quick pointer to another solution to a similar problem: #769264: have a whitelist of modules to bootstrap commandfiles and drupal code.

seanr’s picture

We're finding another need for this functionality not just in preserving hacked code (which we almost never do anyway), but in preventing updates to versions of modules we know will break our sites. Unfortunately, we had a very bad experience with nodewords recently, and we've had other problems with updates to context and stuff like that. We need a way to hold those modules at our existing versions until we can confirm they will not break things.

yingtho’s picture

+1 for .drush-ignore file as well.
Very useful for modules you don't want to update.

boran’s picture

+1 for.drush-ignore too!
For example I don't want GUI editors updated automatically..

moshe weitzman’s picture

Please, no more +1. They are unhelpful and send email to lots of people. We all want this.

naught101’s picture

subscribing.

Ignore file is good, but an --ignore switch that takes multiple arguments would also be very useful, for example, in the instance where you know that a module upgrade requires a bit more work, but is doable, and you have a bunch of other modules that you think will upgrade fine. Then you simply --ignore the troublesome module, upgrade the rest, check the site for problems, then go ahead and upgrade the troublesome module.

dixon_’s picture

I'd like to take this to a higher lever. I think it would be great to be able to "lock" a whole platform, or parts of a platform. Doing drush sql-sync @dev @live could eventually be a disaster overwriting live content with test content. You also might want to lock your live platform from retrieving an rsync from your dev server.

What I'm trying to say is that some kind of generic "lock system" would be very interesting, not only for modules and themes, but for db, core and uploaded files as well.

I might be crazy and currently has no idea how this should work right now. But .drush-ignore feels a little bit too specific for just modules and themes. I'd rather see some generic configuration pattern in one of the *.drushrc.php files.

// Dick Olsson, NodeOne

moshe weitzman’s picture

I think one could try a "lock system" as your own drush command. the command would implement the validate hook for every drush command and would throw an error on the commands that you don't allow. see the api docs that ship in drush3 for more about validate operation. i would think of this as a policy module.

dixon_’s picture

@moshe Yeah, I've did a *very* simple implementation of this, last night trying out the API. Very cool, clean and flexible! I totally can see the point of something like this living in contrib, just because it's quite easy to do. I'll try to get something more complete and working up on d.o the coming weeks (man have I said that before?).

// Dick Olsson, NodeOne

Owen Barton’s picture

A policy module would be great, especially if it could cover some of the more subtle things (e.g. you can view pending updates, but not apply them). I have approached this in the past in a slightly more hacky way by simply checking for forbidden/allowed commands in the server-wide drushrc file and quitting right there and then with a message if it not allowed.

monotaga’s picture

subscribe

stijndm’s picture

I am pro adding a parameter to the module's info file. This is more generic, and other modules could use this as well.

Something like: ignore = true, hacked = true, locked = true, auto update = false, ... Could be anything.

moshe weitzman’s picture

FYI, I just committed an example policy commandfile to core. See http://drupalcode.org/viewvc/drupal/contributions/modules/drush/examples.... It is not really the right solution for this issue though.

greg.1.anderson’s picture

Just a note: I might need to solve this issue soon due to #865674: Make the wiki syntax optional.

gavinengel’s picture

I'd like to be able to include some kind of keyword, like `DRUSH-NO-UPDATE` within a file, and have Drush skip over it (and the rest of the module's files).

I normally put my initials at lines where I've modded a core/popular module, so that I can grep for my initials to see what I've fiddled with. If there was a DRUSH-NO-UPDATE, I'd include that as well.

greg.1.anderson’s picture

I don't think that drush will ever grep every file for no-update flags... one idea I did have, though, was to put a pre-pm-update hook into the hacked module to warn / skip hacked files. This would be a feature of hacked, though, not drush.

gavinengel’s picture

Thanks for pointing out the hacked module. I'm going to try it.

I also realized, that I could have this sort of m.o. for updating:
1. run: drush up
2. grep backups for my initials to see if I had fiddled with any of the modules (which are now backed-up)
3. re-apply the tweaks that I had done earlier

Not too bad, really. I can live with that way of doing updates.

greg.1.anderson’s picture

You could also try kitten-o-matic and see how that works for you. This was an experiment; I'm not actually using it myself at the moment.

Regarding #41, it is not currently possible to use drush hooks to adjust the module selection process in pm-update, but perhaps if pm-update respected "ignore files", then hacked could manage these files in the pre-pm-update hook.

greg.1.anderson’s picture

Status: Needs work » Needs review
FileSize
6.28 KB

This patch allows projects to be locked by creating a ".drush-lock-update" file in the project directory. Using a lock file means that if you lock a project in one Drupal instance, that project is also locked for all other Drupal instances on the same codebase (multi-site installs). Lock files may also be manipulated by other modules (e.g. hacked) in the pre-pm-updatecode hook, if desired.

The lock file contains a message (default: "Locked via drush.") that is displayed in the status table during pm-updatecode time. You may set this message via --lock-message if you want to provide a reminder of why you locked the module. The persistent locks themselves are managed via --lock and --unlock options to pm-updatecode (or pm-update), either of which take a comma-separated list of modules to lock / unlock. Both also accept the special value 'all' to lock or unlock all projects. Managing the locks via options to updatecode rather than via separate commands has two advantages: first, it allows you to also permanently lock modules via $options['lock'] in drushrc.php (or site-by-site by defining command-specific options in a site alias), so you may choose to manage persistent lockfiles via drush configuration options, command-line directives, or touch, per your preference.

A persistent lockfile may be overridden by explicitly naming the project in pm-updatecode or pm-download.

By design, no provision is provided for 'safely' managing your module versions; presumably, if you use this feature, you are updating your code on a dev site that is svn-backed. You can use this feature as a sort of 'safety-net' by setting $options['lock'] = 'all' on production sites, but this only adds a warning -- it does nothing to prevent users from overriding the option.

This patch is pretty simple; it modifies project selection only, and does not alter the logic or flow of the existing update process in any way.

Anonymous’s picture

This sounds very interesting (#44). Let's give this a try. Thank you!

greg.1.anderson’s picture

Community testing welcome and encouraged. ;)

moshe weitzman’s picture

Code looks great. I would change the drush_print('to lock:') and unlock to drush_log(). I think we should drush_log() the skipping of projects so that they show verbose mode. Also, lets support --simulate by running file write/unlink though drush_op().

I think this strikes a nice balance for all the possible concerns.

I hope folks here can help test this, and say if this meets their needs.

greg.1.anderson’s picture

Whoops, those print statements were abandoned debug logic. :( I agree that a log would be good there. I'll have a patch with that + drush_op later today.

xjm’s picture

I like the design of the solution. #44 applies fine. However, I can't seem to get it to create the lock files on the command line using pm-updatecode.

Here is what I see when I try to lock the content_profile module (which I have patched and therefore don't want to upgrade automatically):

drush upc --lock content_profile
Refreshing update status information ...
Done.
to lock:
Array
(
    [0] => 1
)
to unlock:
Array
(
    [0] => 
)

It doesn't seem to actually be creating the lock file using this method. Am I using the wrong syntax?

Edit: I figured it out. It has to be drush upc --lock=content_profile. It seems to me it would make more sense for it to have its own command, though, because otherwise pm-updatecode will chug merrily along and try to update something and you have to hit "no" at the prompt.

Edit: it's also a little annoying to wait for "Refreshing status information..." each time I use the command.

Functionally, though, it successfully excluded projects I locked when I ran pm-updatecode. Very nice!

xjm’s picture

Just noticed that specifying a comma-separated list of projects works with --lock, but not --unlock.

greg.1.anderson’s picture

I'll add checking for --lock and --unlock without parameters. --lock with no parameters will be a no-op, and --unlock will be the same as --unlock=all.

I don't see why unlock should not work with a list, but I'll test that and see if I can reproduce it.

I did consider making lock/unlock a separate command, but rejected that idea for the reasons stated in #44. Locking and unlocking modules will probably be a rare action, so I don't think that performance will be much of an issue long-term. You can always use touch and rm to manage your lock files if you wish, though. drush dd module will tell you the path to your module. You can also pass --no on the command line so that you do not need to explicitly hit 'no' yourself. You could therefore make your own shell alias for lock and unlock; something like alias pm-lock='drush pm-updatecode --no --lock=' (untested).

xjm’s picture

The bash alias should work for me; thanks for the suggestion. I think I'd like to add a switch for pm-updatecode to skip the version refresh check when I know nothing has changed--I disable update.module on production sites for the same reason; it's so darn slow--but that's a separate issue. Edit: at #872920: pm-updatecode option to skip "Refreshing update status information ...".

greg.1.anderson’s picture

FileSize
8.76 KB

Updated patch with changes from #48 and #51. I could not reproduce #50; --unlock with a list worked for me.

moshe weitzman’s picture

From the diff, it looks like the new options apply to pm-enable? If yes, what code calls into drush_pm_update_lock() to make that happen? And if yes, drush_pm_update_lock() is not a good name.

// --unlock with no values is --unlock=all

Not so sure about this. We should consider making this a no-op as well. Lets try not to blow away the lock files when we get an ambigous option value.

Once these are addressed, feel free to commit.

greg.1.anderson’s picture

Status: Needs review » Fixed

Lock and unlock do not apply to pm-enable; that was an illusion of the diff.

Committed with warnings when --lock and --unlock are used without values, in which case they are ignored.

naught101’s picture

Nice work. Perhaps it would make sense to have --unlock have a yes/no prompt for unlocking all? It'd definitely be a useful option to have sometimes.

xjm’s picture

#56: I think --unlock=all still works.

Thanks again for this patch. This is my favorite thing about drush since... well, since drush.

greg.1.anderson’s picture

Yep, --unlock=all still works. Glad you like the feature; it's working well for me too. I just sort of wish I had fixed it in Drupal update status; my locked modules are bugging me that they need to be updated. :p

Maybe someday.

naught101’s picture

nice

Anonymous’s picture

works purrrfect. thank you very much!

Status: Fixed » Closed (fixed)

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

Cyberwolf’s picture

Component: Code » PM (dl, en, up ...)

Great new feature! For those who want to try it out without patching: it seems to be only available in the HEAD dev releases (not in 3.x-dev where I was first looking).

bibo’s picture

Posted by Owen Barton on April 29, 2009 at 12:00am

Note, that update_advanced has the ability to ignore updates on certain projects (as update_status did in 5.x). We should probably check that if we can, although a .drush-ignore would be good in addition, as would a hook to allow you to wire in your own patch management checks.

I'm not sure if you're aware of this, but drush automatically respects the settings of the update_advanced-module. I assume this works because drush uses the update-module for the updates, and update_advanced integrates with it.

So if I have set "views" to update "never" at http://example.com/admin/reports/updates/settings , "drush up views"... It will show Views as "Unable to check status " and respond "No code updates available." (even if there are updates).

Surprisingly, this feature is not documented anywhere (!), at least not in drush or update_advanced'sissue queues (drush & update_advanced).

It's very useful, we have been using it in our workflow for over a year now. This is the reason we even use update_advanced, and I believe a lot of other people would too, if it was somehow documented.

PS: I also believe this is a lot easier to use than a --lock option, but either way it's important that we can set patched modules to not be updated by drush.

datarazor’s picture

don't want to bandwagon, but what about a drush command that just compares a module / core with what is on the server to see if any changes have happened?
drush diff images
Wouldn't that also help if you are inheriting a project and you see lots of modules in -dev version and you suspect local hacking? the thinking is that not every other drupal prgrammer will think to "lock" a mpdule if they hack it, so this method of flagging only works if the previous developer was aware of making good use of flag and locks. The alternative would be that Drupal [specifically: update-check] detects changes from release versions, and auto-flags a module as "changed"; this would be IDEAL. As it would eliminate human error/failing...

Just a thought.

greg.1.anderson’s picture

See #17. The hacked module even comes with drush pm-updatecode integration, so if you modify a module, hacked will automatically lock it via drush so that pm-updatecode won't touch it any more.

donquixote’s picture

For those who ended up here from a google search and don't want to read all replies, here is a

Link to the related documentation page.
Excluding projects from updatecode

salientknight’s picture

Title: Have drush update be told to ignore a module/theme » Have drush update be told to ignore a module/theme -- simple solution

Just an observation...

site offline

$ cd sites/all/modules/                 //(and/or sites/all/themes)
$ mv <your module or theme>  /tmp/<your module or theme>  
$ drush --uri=<yoursite> up 
$ drush updb
$mv  /tmp/<your module or theme>  <your module or theme> 

site back up

This works great for excluding what you don't want updated and takes about two seconds. If the files are not in the modules path, they are not updated.

If you routinely want to skip the same folders create a simple shell script that moves the directories, runs up and then moves them back.
Hope some of you find this useful.

gavinengel’s picture

Although, picture this. You have dozens of Drupal sites, some you created and some others created. How confident are you that you know which modules have been hacked for a custom purpose?

The best answer IMHO is for Drush to download the current version, diff it with what is in place, then update *only* of there are no differences.

[edit] Yes, I know there are modules that can do diff'ing. But having this feature built into Drush would make life much easier.

naught101’s picture

izmeez’s picture

[edit] Please ignore this.
Did this get committed to drush 4.4 or is it closed because of the automatic comment #61 ?
The --lock and unlock commands don't appear to be in drush 4.4
[/edit]

My apologies. More careful reading of the comments helped me understand the proper syntax for a multisite setup is

drush up -l http://example.com --lock=module_name

And yes it does work in drush 4.4

Thanks.

xjm’s picture

#70: It's in the 5.x branch. Not sure about 4.x.

izmeez’s picture

@xjm Thanks for the fast reply, I was just editing my comment #70 having discovered the right syntax.