The first version of this patch will load aliases from the new location or drushrc.php. We can decide whether to remove the current mechanism, or keep it in place. Because of the way aliases work, we would have to go out of our way to prevent them from being defined in drushrc.php, so perhaps it should remain a sanctioned place.

There will be a default search path for the alias file location, which will default to the drush install directory, /etc and $HOME/.drush, and additional folders can be specified in any drushrc.php file loaded during the DRUSH_BOOTSTRAP_DRUSH phase, or via command-line options.

Inside the search path, drush will look for files named 'aliases.drushrc.php' and '$aliasname.alias.drush.php'.

Alias definitions will be searched for when they are referenced. Every time a local site is referenced by an alias, its site folder will be added to the alias file search path, so site-specific aliases (e.g. '@peer') may be defined.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

moshe weitzman’s picture

thanks for kicking this off.

i don't want two different ways of doing things. i'd rather not allow aliases in drushrc and if we must, lets not advertise as a feature ... i have no desire to provide backwards compat for 3.0 since it isn't released yet.

greg.1.anderson’s picture

Status: Active » Needs review
FileSize
27.25 KB

This patch includes the code from #733244: Aliases should be named '@alias' instead of 'alias' and #727058: Site aliases should not be cached in the options context.

The main logic looks like this:

function _drush_sitealias_load_alias($alias) {
  // Only aliases--those named entities that begin with '@'--can be loaded this way.
  // We also skip any alias that has already been loaded.
  $all_site_aliases =& drush_get_context('site-aliases');
  if ((substr($alias,0,1) == '@') && !array_key_exists($alias,$all_site_aliases)) {
    $aliasname = substr($alias,1);
    drush_sitealias_load_all($aliasname);
  }
}

function drush_sitealias_load_all($aliasname = NULL) {
  $alias_files = array('aliases.drushrc.php');
  if ($aliasname != NULL) {
    $alias_files[] = $aliasname . '.alias.drushrc.php';
  }
  $alias_path = (array) drush_get_option('alias-path', array());
  if (empty($alias_path)) {
    $alias_path[] = drush_get_context('ETC_PREFIX', '') . '/etc/drush';
    $alias_path[] = dirname(__FILE__) . '/..';
    $alias_path[] = dirname(__FILE__) . '/../aliases';
    if(!is_null(drush_server_home())) {
      $alias_path[] = drush_server_home() . '/.drush';
    }
  }
  foreach ($alias_path as $path) {
    $alias_files_to_consider = $alias_files;
    if ($aliasname == NULL) {
      $alias_files_to_consider = array_merge($alias_files_to_consider, array_keys(drush_scan_directory($path, '/.*\.alias\.drushrc\.php/', array('.', '..', 'CVS'))));
    }
    foreach ($alias_files_to_consider as $filename) {
      $full_path = (substr($filename,0,1) != '/' ? $path . '/' : '') . $filename;
      if (file_exists($full_path)) {
        $aliases = array();
        include $full_path;
        $options = array();
        if ($aliasname == NULL) {
          $options['site-aliases'] = $aliases;
        }
        elseif (array_key_exists($aliasname, $aliases)) {
          $options = array();
          $options['site-aliases'][$aliasname] = $aliases[$aliasname];
        }
        if (!empty($options)) {
          drush_set_config_options('alias', $options);
        }
      }
    }
  }
}

_drush_sitealias_load_alias is called whenever a command looks up an alias ("@aliasname") via drush_sitealias_get_record. Note that under this implementation, we do not cache alias records in any context unless the alias is fetched; unused aliases are ignored.

drush_sitealias_load_all is called only by the drush site-alias command, and only when there are no parameters. It fetches every alias it can find, and prints its name (or the whole thing if --full is used).

Finally, this patch prevents aliases from being defined in drushrc.php files via a call to unset($options['site-aliases']); placed immediately after the drushrc.php file is loaded. It is still possible to nest alias records (define one alias inside another).

Yes, the documentation needs to be updated now, but this is a good starting point for further discussion.

moshe weitzman’s picture

That excerpted code and explanation look good to me. As you said, lets get some doxygen in here before commit ... adrian is planning to review this over the weekend.

greg.1.anderson’s picture

After sleeping on it, it was my consideration that this snippet:

        $aliases = array();
        include $full_path;
        $options = array();

Should instead be:

        $aliases = $options = array();
        include $full_path;

This would allow myalias.alias.drush.php to define $options the same way that they are defined in drushrc.php, or it can define an alias the same way that it would be defined in aliases.drushrc.php. This would also require some small changes to the alias processing on the lines below, to insure that $options became part of the alias. This feature would also benefit aliases.drushrc.php in that you could define some $options at the top of the file, and they will be applied to all aliases in the file. This also implies that perhaps the code should look for *.aliases.drushrc.php in addition to aliases.drushrc.php, so that people could make groups of aliases, if desired.

I'll try to update tonight, but it is not likely I will have time to do it. I'll add doxygen and example.aliases.drushrc.php, and update example.drushrc.php after Adrian's review.

greg.1.anderson’s picture

Here's a patch that includes the ideas from #4. This allows you to define an alias file that looks like this:

servername.aliases.drushrc.php:

$options['remote-host'] = 'servername.domain.com';
$options['remote-user'] = 'publisher';

$aliases[mylivesite'] = array (
  'uri' => 'http://mysite.com',
  'root' => '/srv/www/drupal',
);

$aliases['myotherlivesite'] = array (
  'uri' => 'http://myothersite.com',
  'root' => '/srv/www/drupal',
);

The $options are copied into every alias.

Similarly, put this in your 'sites' folder to define an alias @peer, valid only for that site:

peer.alias.drushrc.php:

$options['remote-host'] = 'servername.com';
$options['remote-user'] = 'publisher';
$options['uri'] = 'thelivesite.com';
$options['root'] = '/srv/www/drupal';

You can also use $aliases['peer'] = array(...) if you prefer.

adrian’s picture

Status: Needs review » Needs work

I have tested this patch, and it seems to be working fine. I also like how it's been implemented. AFAICT it's not possible to set aliases in a drushrc.php anymore.

I'm still a bit unclear about a couple of things.

If both ~/.drush/aliases.drushrc.php and ~/.drush/aliasname.alias.drushrc.php are defined, which one takes precedence?

I also feel that we should be using a subdirectory in ~/.drush (or /etc/drush, or wherever), to keep the alias definitions together.

This has become a bit of a hydra of a patch, so i think we should close the other related items and hash it all out here.

(setting it to needs work, because that's the closest to what the actual status is ... i feel this patch is very nearly there)

adrian’s picture

Something I will likely be using, and might have to implement myself is inheritance.

IE : each alias can have a parent alias.

Similar to your first example regarding the options but the 'servername.alias.php' defines only remote_host / remote_user.
Then the platformname.alias.php defines only the drupal root, and then the sitename.alias.php defines just the URI component.

This means I can keep them up to date separately.

Your second format (ie: $options), actually allows me to simply include the necessary parent from my generated site alias record.

greg.1.anderson’s picture

Status: Needs work » Needs review

Can I suggest that if there are no immediately obvious bugs in this issue (and the two it depends on) that we go ahead and commit it, mark it fixed, and continue with additional enhancements in separate issues? I'll accept necessary changes here, but some of the enhancements, I think, would be easier to discuss in separate issues where the diffs can be smaller.

You are right -- based on a comment by Moshe, I explicitly prohibit alias definitions in drushrc.php from working. They could be allowed again by removing one 'unset' from the code and adding back in the $aliases to $options['site-aliases'] copy that was there before.

Regarding precedence, right now it is not defined. The loop does not terminate, so the last encountered alias will win. If a 'terminate when found' condition is put in, then the first encountered alias could win. Precedence could be adjusted by tuning the order of the search path and search files. I tend to think that most people won't mix the different kinds of alias files, so precedence will not be a big issue.

The current places that alias files are searched for are as follows:

/etc/drush
DRUSH
DRUSH/aliases
$HOME/.drush

This could easily be changed to:

/etc/drush/aliases
DRUSH/aliases
$HOME/.drush/aliases

... or the two lists could be merged. It's possible to define what the search path should be by setting $options['alias-path'] = '/etc/drush/aliases' in drushrc.php, so adjusting the default search path is not critical, IMO. This does need to be documented, but I'm holding off on documentation until we're agreed on core features & this patch is committed.

You are right that inheritance would not be too hard to implement, and can to a certain extent be achieved today via $options syntax and 'include'. I'd suggest future enhancements in this area be discussed in a separate issue.

I don't think any of the above changes need to be made; if you'd like any of the suggestions above implemented, let me know explicitly which way you think it should go and I'll roll another patch. Otherwise, let's go ahead and get this committed.

Thanks for your review.

adrian’s picture

Status: Needs review » Needs work

In a completely non-pedantic way, I think we should go through the documentation, the following functions are missing phpdoc :

function _drush_sitealias_get_record($alias, $db_settings_needed = false) {} // more than 100 lines of code !
function drush_sitealias_alias_path($add_path = NULL) {}
function _drush_sitealias_load_alias($alias) {}
function drush_sitealias_load_all($aliasname = NULL) {} // i think this is misnamed
function drush_sitealias_add_db_url(&$alias_record) {} 
function drush_sitealias_add_db_settings(&$alias_record) {}
function drush_sitealias_resolve_path_references(&$alias_record, $test_string = '') {}
function drush_sitealias_resolve_sitelist($alias_record) {}
function drush_sitealias_check_lists_alignment($source, $target) {}
function drush_sitelist_align_lists(&$source, &$target, &$source_result, &$target_result) {}
function _drush_sitelist_check_site_records($source, $target) {}
function drush_sitealias_resolve_sitespecs($site_specifications, $db_settings_needed = false) {}
function _drush_sitealias_check_sitelist_fields(&$alias_record) {}
function _drush_sitealias_derive_record($from_record, $modifying_record) {}
function drush_sitealias_build_record_from_settings_file($site_settings_file, $alias = null, $drupal_root = null) {}
function drush_sitealias_convert_db_from_db_url($db_url) {}

The missing documentation and the rather esoteric operation of this stuff means that there is a rather high WTF quotient if you are not used to the code. Not a dealbreaker, but still isn't making this any easier.

adrian’s picture

Status: Needs work » Reviewed & tested by the community

greg .. i am fine with this being committed, and work being done on it further.

fyi ..the sitelist functonality is also broken.

greg.1.anderson’s picture

I'll look into the sitelist feature and repair as required, and then I will document the code and commit.

Repairing _drush_sitealias_get_record will have to wait for a later time -- hopefully not too much later. I want to get rid of the evil that is $db_settings_needed too.

adrian’s picture

i was trying with :

drush @sitealias1,@sitealias2 status

greg.1.anderson’s picture

Yeah, that should work all right. I'll look into it and see what broke it.

greg.1.anderson’s picture

For reference, here is the fix for the bug in #12.

I'll commit this whole thing once I've put in some doxygen.

greg.1.anderson’s picture

Status: Reviewed & tested by the community » Fixed

Committed. Docs still need need some help (especially example.aliases.drushrc.php), but I've made a decent start.

Status: Fixed » Closed (fixed)

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