Download & Extend

Add "pm-" namespace to all of the pm commands

Project:Drush
Version:All-versions-5.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:closed (fixed)

Issue Summary

This patch renames "update" to "pm-update", and so on. The former names are included in the deprecated aliases list, which work, but emit a warning message when used.

Otherwise, no new aliases are added by this patch.

AttachmentSize
pm-namespace.patch6.42 KB

Comments

#1

This is fine by me - I assume this will allow us to use the namespaces (now/in future?) to filter commands etc? Certainly moving to hyphenated commands will make the autocomplete patch way easier.

#2

Per Moshe; see the discussion in #550522: Change white spaces in commands by another symbol. The namespace is not consistent or enforced yet; just moving in that direction.

#3

Status:needs review» needs work

pm-enable is not working for me. It doesn't actually execute the callback. Looks like drush_invoke is looking for drush_pm_pm_enable() [ugh] and we have drush_pm_enable().

@owen - help filtering is working nicely in HEAD with something like: drush | grep "sql-"

#4

Status:needs work» needs review

Dang, that drush_invoke has poked me in the eye so many times I've gone blind on one side.

Here's a new patch, this time with all functions tested (instead of just the one singular one that did not use drush_invoke). The function replacements I did were:

find -exec grep -Hi 'function drush_pm_' {} \;
./commands/pm/pm.drush.inc:function drush_pm_pm_enable() {
./commands/pm/pm.drush.inc:function drush_pm_pm_disable() {
./commands/pm/pm.drush.inc:function drush_pm_pm_uninstall() {
./commands/pm/pm.drush.inc:function drush_pm_pm_info() {
./commands/pm/pm.drush.inc:function drush_pm_pm_refresh() {
./commands/pm/pm.drush.inc:function drush_pm_pm_update() {
./commands/pm/pm.drush.inc:function drush_pm_post_pm_update() {
./commands/pm/pm.drush.inc:function drush_pm_post_pm_updatecode() {
./commands/pm/pm.drush.inc:function drush_pm_pm_download() {
./commands/pm/updatecode.inc:function drush_pm_updatecode() {

Which matches up pretty well with this:

$ drush | grep 'pm-'
pm-enable (en) Enable one or more modules.
pm-disable (dis) Disable one or more modules.
pm-uninstall Uninstall one or more modules.
pm-statusmodules Show module enabled/disabled status
pm-refresh (rf) Refresh update status information
pm-updatecode (upc) Update your project code
pm-update (up) Update your project code and apply any database updates
pm-info Release information for a project
pm-download (dl) Download core Drupal and projects like CCK, Zen, etc.

(Neat trick, drush | grep.)

AttachmentSize
pm-ns-with-drush-invoke.patch 9.93 KB

#5

I'm not that thrilled with the overly verbose drush_pm_pm_enable() replacing drush_pm_enable. Can we convince drush_invoke() to be more terse here? Sorry to send you back into battle - wear goggles!

adrian and i are discussing how to push all commands through drush_invoke at #625920: Commands with explicit callback functions skip drush_invoke() API

#6

You know, I remembered reading that issue (explicit callback fns skip drush invoke) some time back, and thought that maybe I should go back and fix it just as penance for forgetting drush_invoke so often. ;)

I did consider what you suggested above in #5, but decided against it because of the large number of variants. For example, drush_pm_pm_enable also has drush_core_pm_enable and drush_sql_pm_enable, most of which will never exist, and only one of which will be simplified. I also know that there are some existing drush_sql_sql_xxx functions that I'll break when I do that... but I'll put on my goggles and wade in.

#7

Smart monkey uses tools.

$ find -exec grep -Hi 'function drush_\([a-zA-Z]\+\)_\1' {} \;
./commands/pm/pm.drush.inc:function drush_pm_pm_enable() {
./commands/pm/pm.drush.inc:function drush_pm_pm_disable() {
./commands/pm/pm.drush.inc:function drush_pm_pm_uninstall() {
./commands/pm/pm.drush.inc:function drush_pm_pm_info() {
./commands/pm/pm.drush.inc:function drush_pm_pm_refresh() {
./commands/pm/pm.drush.inc:function drush_pm_pm_update() {
./commands/pm/pm.drush.inc:function drush_pm_pm_download() {
./commands/core/variable.drush.inc:function drush_variable_variable_get() {
./commands/core/variable.drush.inc:function drush_variable_variable_set() {
./commands/core/variable.drush.inc:function drush_variable_variable_delete() {
./commands/sql/sync.sql.inc:function drush_sql_sql_sync($source = null, $destination = null) {

$ find -type f -exec sed -i -e 's/\(function drush_\)\([a-zA-Z]\+\)\(_\2\)/\1\2/' {} \;

Note that my regexpr was deliberately crafted to eliminate only directly-adjacent occurrence of the namespace portion of the function name. For example, in the case of drush_pm_post_pm_update(), we want both of the "pm"s to stay in the function name. We can't get rid of the first one, because it's part of the drush coding standards that function names should start "drush_ns_", and it would be undesirable to get rid of the second one, because that would be too hard to document.

In testing this change, I discovered that #550522: Change white spaces in commands by another symbol broke sql-sync (and any other command that appears in its own command file). This patch also fixes that bug.

I even went so far as to test all of the commands I changed, and a couple I didn't. ;)

Needs documentation, but please take a look first; if you like it, I'll comment and commit.

AttachmentSize
drush-invoke.patch 11.33 KB

#8

Thinking of command names... we have:

* `status` = birds-eye view of the current Drupal
* `pm-statusmodules` = list of modules name, description and status (enabled/disabled)
* and I have `theme-status` in #530780: drush commands to administer themes, that provides a list of theme name, title, description and status similar to statusmodules

I suggest to rename `pm-statusmodules` to `pm-status-modules` so we can implement `pm-status-themes` and why not `pm-status-profiles` and perhaps `pm-status-libraries`. Additionally `status-search` could be an alias for `search-status`.

#9

We unify command names for download, enable, disable, info. lets nify under pm-status, instead of one for each project type.

#10

Status:needs review» reviewed & tested by the community

#7 looks good to me.

a followup task which i started but never got anywhere near done; add a debug log entry showing all possible drush_invoke() variations. it would be a long list, but helpful IMO. probably just space delimit each function. if we have to loop over the list twice, thats fine. is OK to log rollback separately.

#11

Status:reviewed & tested by the community» needs review

I forgot to mention above that you need to rename commands/pm/updatecode.inc to commands/pm/updatecode.pm.inc for these modifications to work. Do you have any special procedure (recordkeeping) for moving files, or should I just go ahead and cvs remove / cvs add?

I'm not sure I understand what you want in #9. Rename pm-statusmodules to pm-status, and have it get status on themes, profiles, modules, etc.?

#12

in theme-list there're two extra columns for Default and Administration theme (yes/no). We could suppress them and add two lines to status (core).

So unifying `statusmodules` and `theme-list` in pm-status is possible but I prefer to rename `statusmodules` to `pm-list` as statusmodule can suggest it shows an update status.

I think also of `info` command. It provides releases info. I use `theme-info` that provides detailed info about a theme (engine, stylesheets, etc). There's no equivalent command for modules (to show dependencies, ...). We could use `pm-releases` replacing current `info`and introduce new `pm-info`.

I'm trying to not hijack issues so my proposal here is cleanly the following renaming:
* statusmodules -> pm-list
* info -> pm-releases

and based on that, other issues will evolve in one or another way.

#13

#11 - yes, just cvs remove and cvs add. its a pain to do anything more fancy.

#12 - pm-list and pm-releases sound very good to me. in #654682: drush statusmodule --package: Package column and grouping for the statusmodules list, we should remove the project description to make room for other data like 'project type'.

#14

Okay, I'll do the pm-list and pm-releases renaming when I fix up the documentation for drush_invoke later today or Sunday.

#15

subscribing and if some work is needed with #654682: drush statusmodule --package: Package column and grouping for the statusmodules list please let me know in there.

#16

Status:needs review» fixed

Committed with documentation. I also slipped in some (temporary) backwards compatibility for contrib commands that might be using the "drush_foo_foo_xxx" naming convention (functions with the old name produce an annoying nag error in the log).

#17

this just broke aegir horribly.

it's basically forcing me to rename all of my functions. and there are hundreds of them.

#18

Status:fixed» needs work

Sorry about that.

Is the backwards-compatibility code not working in Aegir?

    foreach ($list as $commandfile => $filename) {
      $oldfunc = sprintf("drush_%s_%s", $commandfile, $var_hook);
      $func = str_replace('drush_' . $commandfile . '_' . $commandfile, 'drush_' . $commandfile, $oldfunc);
      if (($oldfunc != $func) && (function_exists($oldfunc))) {
        drush_log(dt("The drush command hook naming conventions have changed; the function !oldfunc must be renamed to !func.  The old function will be called, but this will be removed shortly.", array('!oldfunc' => $oldfunc, '!func' => $func)), "error");
        // TEMPORARY:  Allow the function to be called by its old name.
$functions[] = $oldfunc;
      }
      if (function_exists($func)) {
        $functions[] = $func;
      }
    }

This was working with the pm module when I tested it. The call to drush_log is flagged as an "error" even though it should really be a "warning" or even a "notice". Does Aegir work okay if this log is changed to a notice, or is the backwards-compatible feature in fact broken?

#19

Status:needs work» postponed (maintainer needs more info)

Is this working in Aegir now? If you'd like to get rid of all of the warnings, you can run the grep and sed commands from #7, above on the Aegir source code. You should be prepared to roll back, but this should "just work".

Preflight: see which commands need to be changed

$ find -exec grep -Hi 'function drush_\([a-zA-Z]\+\)_\1' {} \;

Edit: Rename all commands to match the new naming scheme

$ find -type f -exec sed -i -e 's/\(function drush_\)\([a-zA-Z]\+\)\(_\2\)/\1\2/' {} \;

#20

I'm sad about this.
From a casual user perspective, the commandline has now taken a few steps back into the arcane.

I understand why the code is marginally better by using a namespace.
But I think it's significantly worse by not using plain English and intuitive names any more.

This will badly hinder any adoption curve, IMO.

Comparing with tools like CVS, git and svn, this prefix is ugly. It's not the users job to know or care which code file is providing the function, just that the named function exists. Making the user do extra work every single time they type so that the magic internal function-name-scanner finds the pattern easier to guess is not helpful.
Even though I've already created my own namespace conflict just within my own experiments, I think that core drush commands are allowed to be exempt from any rule like that. They can own the name, they win.

#21

Use command aliases

#22

:-(
The provided aliases are also arcane.
The "extra work" is not the typing, it's recalling and translating what you want to do into a made-up application-specific cipher each time.

If I update using cvs, I type:
cvs update

If I want to update using drush, it's now
drush {something drush-specific I'm supposed to have remembered}

I know that if you develop actively on the internals, it's obvious that "update is part of package manger which is in a file called pm so that's what it's called, and the alias is not 'ud' ".
But IMO that's a really hard thing for users who may use this a few times a month to remember.

I guess we can deal with it, it only took me 6 years to remember the more common options for 'tar' and 'find'. And those ones were not being deliberately obsfuscated with 'namespaces'
But making the commandline harder to use seems retrograde.
Also impressive, I hadn't considered it possible until now :-B

#23

You have a real point here, but your laziness is getting in the way. Please suggest better command names and alias names. Feel free to dream and reorganize them as needed.

Also, I see no reason why we can't add an alter after command files are gathered so that a personal command file can add own aliases.

#24

@dman: It's not so bad as all that! All of the old pm-xxx commands have deprecated aliases in pm.drush.inc. You can keep using the alias if you want. If there is general agreement that a given command name should continue to exist in its original form, all that needs to be done is to move the deprecated alias to the aliases list, and it will be back in the command help again.

I agree with Moshe here; just make a new issue if you'd like to see some of the old commands come back. Some of them definitely should, but I for one like "pm-list" better than "statusmodules", so I'd say that the namespace has helped in a couple of instances.

#25

Normally I'm staunchly on the coder side of things, so I feel a bit odd speaking up for the UX side :-)
Sorry for being contrarian, but on this thing I'm offering a "users" view. (though I am now very familiar with drush internals also)

We have consistency (prefix them ALL) and code conventions (namespaces allow some code abstraction short-cuts) vs "Why make it more complicated and obscure?"

Sure, "pm-list" is not worse than "statusmodules". Can't say it's better. Can't say it's intuitive or memorable.
What's wrong with 'module-status' module-list or package-list? English.

If anything, I think we can learn from apt-get (and CVS). Can't remember rpm.
Re-use terminology already in use:
apt-get

Commands:
   update - Retrieve new lists of packages
   upgrade - Perform an upgrade
   install - Install new packages (pkg is libc6 not libc6.deb)
   remove - Remove packages
   source - Download source archives
   build-dep - Configure build-dependencies for source packages
   dist-upgrade - Distribution upgrade, see apt-get(8)
   dselect-upgrade - Follow dselect selections
   clean - Erase downloaded archive files
   autoclean - Erase old downloaded archive files
   check - Verify that there are no broken dependencies

I know it's not exactly the same, but why not install instead of pm-download? CPAN uses or get. That's sweet enough.

Reduce the un-learning needed.

Pear
(Abrigded)

build                  Build an Extension From C Source
clear-cache            Clear Web Services Cache
config-create          Create a Default configuration file
config-get             Show One Setting
config-help            Show Information About Setting
config-set             Change Setting
config-show            Show All Settings
convert                Convert a package.xml 1.0 to package.xml 2.0 format
cvsdiff                Run a "cvs diff" for all files in a package
cvstag                 Set CVS Release Tag
download               Download Package
download-all           Downloads each available package from the default channel
info                   Display information about a package
install                Install Package
list                   List Installed Packages In The Default Channel
list-all               List All Packages
list-channels          List Available Channels
list-files             List Files In Installed Package
list-upgrades          List Available Upgrades
login                  Connects and authenticates to remote server [Deprecated in favor of channel-login]
logout                 Logs out from the remote server [Deprecated in favor of channel-logout]
makerpm                Builds an RPM spec file from a PEAR package
package                Build Package
package-dependencies   Show package dependencies
package-validate       Validate Package Consistency
pickle                 Build PECL Package
remote-info            Information About Remote Packages
remote-list            List Remote Packages
run-scripts            Run Post-Install Scripts bundled with a package
run-tests              Run Regression Tests
search                 Search remote package database
shell-test             Shell Script Test
sign                   Sign a package distribution file
svntag                 Set SVN Release Tag
uninstall              Un-install Package
update-channels        Update the Channel List
upgrade                Upgrade Package
upgrade-all            Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]

... What I see there is that where it does "namespace" or concatenate words into commands, it at least does not do so with an acronym. We can learn from that.

instead of pm-refresh - package-refresh is friendlier. I don't mind the length (much). It's about the logic.
It's about seeing this commandline syntax in an inheirited bash script or a help file in a years time and saying "I see what they are doing there" rather than "Huh?"

(pro-tip - when writing a bash script for posterity, use long commandline options, not short ones. Those who come after you will appreciate self-documenting code.)

CPAN

Download, Test, Make, Install...
get      download                     clean    make clean
make     make (implies get)           look     open subshell in dist directory
test     make test (implies make)     readme   display these README files
install  make install (implies test)  perldoc  display POD documentation

Upgrade
r        WORDs or /REGEXP/ or NONE    report updates for some/matching/all modules
upgrade  WORDs or /REGEXP/ or NONE    upgrade some/matching/all modules

... stand on the shoulders of giants! All these ones use real words.

I'm sure the system can easily support the old aliases without any trouble. So that's fine. I'd still prefer the 'human' name to be the primary command, but an alias will work around my 'laziness'.

... though I'd rather that was intrinsic rather than user-configured. The point of drush (sync family anyway) is that it's running on different machines as different users. Introducing personal user confs for the names of commands in multiple places would be agony.

Some of what I'm saying is laziness, yep. Guilty. But I also think there is a big point to be made for readability, intuition, and pre-existing conventions on how better people than me use the commandline. Deliberate obscurity would be unfortunate.

#26

Okay, posting all of those examples was definitely un-lazy. But what I think that Moshe meant by lazy was that rather than complain about the way it is, you should make a patch that improves the situation and attach it to a new incident with an appropriate explanation / justification.

#27

I must say, the reasons dman gives were the same ones why we went from "pm command"
to "command" in the first place (1.x to 2.x). Given that the pm commands (unlike most of the other commands) have very close analogs in other *nix veteran tools I think it is reasonable to make an exception. Quite what "exception" means however, I think needs definition - (a) do we just "undepreciate" the original aliases, (b) do we make the original aliases the command names (and/or leave the pm- ones as aliases), (c) do we figure a way to have the pm- ones the "real" command names, but show the friendly ones in help (d) make each pm command essentially it's own namespace (update, update-db, update-code could perhaps share?) (e) something else...

I think a command alter is certainly a good thing, but I think is a separate issue as it has many possible use cases (actually I think there may need to be 2+ alters - one for altering the "functional" command set used and one for just altering the command help etc presented to the user).

#28

Some systems allow you to enter just the first few characters of a command to select it. We could take this concept and extend it to search after the namespace portion of a command. Exact matches would be checked first, so aliases always win without disambiguation, but if there is no exact match, the user could be prompted for which command was intended if there were multiple partial matches.

In this way, you could run all of the pm commands via their simple names; 'pm-enable' could just be 'enable'. If someone defined a new command 'mylittlepony-enable', then you would have to use 'pm-enable' to disambiguate (or select the correct command via drush_choice).

If there is interest in this technique, I'll write the patch.

#29

Status:postponed (maintainer needs more info)» closed (fixed)

I think all of this is settled now. Please re-open if needed.

nobody click here