function drush_get_projects

8.0.x drush_get_projects(&$extensions = NULL)
6.x drush_get_projects(&$extensions = NULL)
7.x drush_get_projects(&$extensions = NULL)
3.x drush_get_projects()
4.x drush_get_projects(&$extensions = NULL)
5.x drush_get_projects(&$extensions = NULL)
master drush_get_projects(&$extensions = NULL)

Obtain an array of installed projects off the extensions available.

A project is considered to be 'enabled' when any of its extensions is enabled. If any extension lacks project information and it is found that the extension was obtained from's cvs or git repositories, a new 'vcs' attribute will be set on the extension. Example: $extensions[name]->vcs = 'cvs';


array $extensions: Array of extensions as returned by drush_get_extensions().

Return value

Array of installed projects with info of version, status and provided extensions.

Related topics

4 calls to drush_get_projects()
drush_pm_updatecode in commands/pm/
Command callback. Displays update status info and allows to update installed projects. Pass specific projects as arguments, otherwise we update all that have candidate releases.
pm_complete_projects in commands/pm/
List projects for completion.
updatexml_get_releases_from_xml in commands/pm/release_info/
Obtain releases for a project's xml as returned by the update service.
_drush_make_generate_projects in commands/make/
Generate the $projects makefile array for the current site.


commands/pm/, line 449
The drush Project Manager


function drush_get_projects(&$extensions = NULL) {
  if (is_null($extensions)) {
    $extensions = drush_get_extensions();
  $projects = array(
    'drupal' => array(
      'label' => 'Drupal',
      'version' => VERSION,
      'type' => 'core',
      'extensions' => array(),
  foreach ($extensions as $extension) {
    // The project name is not available in this cases:
    // 1. the extension is part of drupal core.
    // 2. the project was checked out from CVS/git and cvs_deploy/git_deploy
    // is not installed.
    // 3. it is not a project hosted in
    if (empty($extension->info['project'])) {
      if (isset($extension->info['version']) && ($extension->info['version'] == VERSION)) {
        $project = 'drupal';
      else {
        if (is_dir(dirname($extension->filename) . '/CVS') && (!module_exists('cvs_deploy'))) {
          $extension->vcs = 'cvs';
          drush_log(dt('Extension !extension is fetched from cvs. Ignoring.', array('!extension' => $extension->name)), 'debug');
        elseif (is_dir(dirname($extension->filename) . '/.git') && (!module_exists('git_deploy'))) {
          $extension->vcs = 'git';
          drush_log(dt('Extension !extension is fetched from git. Ignoring.', array('!extension' => $extension->name)), 'debug');
    else {
      $project = $extension->info['project'];
    // Create/update the project in $projects with the project data.
    if (!isset($projects[$project])) {
      $projects[$project] = array(
        // If there's an extension with matching name, pick its label.
        // Otherwise use just the project name. We avoid $extension->label
        // for the project label because the extension's label may have
        // no direct relation with the project name. For example,
        // "Text (text)" or "Number (number)" for the CCK project.
        'label' => isset($extensions[$project]) ? $extensions[$project]->label : $project,
        'type' => $extension->type,
        'version' => $extension->info['version'],
        'status' => $extension->status,
        'extensions' => array(),
      if (isset($extension->info['project status url'])) {
        $projects[$project]['status url'] = $extension->info['project status url'];
    elseif ($extension->status != 0) {
      $projects[$project]['status'] = $extension->status;
    $projects[$project]['extensions'][] = $extension->name;

  // Obtain each project's path and try to provide a better label for ones
  // with machine name.
  $reserved = array('modules', 'sites', 'themes');
  foreach ($projects as $name => $project) {
    if ($name == 'drupal') {

    // If this project has no human label and it only contains an extension,
    // construct a label based on the extension name.
    if (($project['label'] == $name) && (count($project['extensions']) == 1)) {
      $extension = $extensions[$project['extensions'][0]];
      $projects[$name]['label'] = $extension->info['name'] . ' (' . $name . ')';

    drush_log(dt('Obtaining !project project path.', array('!project' => $name)), 'debug');
    $path = _drush_pm_find_common_path($project['type'], $project['extensions']);
    // Prevent from setting a reserved path. For example it may happen in a case
    // where a module and a theme are declared as part of a same project.
    // There's a special case, a project called "sites", this is the reason for
    // the second condition here.
    if ($path == '.' || (in_array(basename($path), $reserved) && !in_array($name, $reserved))) {
      drush_log(dt('Error while trying to find the common path for enabled extensions of project !project. Extensions are: !extensions.', array('!project' => $name, '!extensions' => implode(', ', $project['extensions']))), 'error');
    else {
      $projects[$name]['path'] = $path;

  return $projects;