Index: libraries.api.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/libraries/libraries.api.php,v
retrieving revision 1.3
diff -u -p -r1.3 libraries.api.php
--- libraries.api.php	22 Sep 2010 17:00:56 -0000	1.3
+++ libraries.api.php	28 Sep 2010 21:04:33 -0000
@@ -330,3 +330,25 @@ function hook_libraries_info_alter(&$lib
   );
   $libraries['php_spellchecker']['integration files']['example_module'] = $files;
 }
+
+/**
+ * Specify additional library paths.
+ *
+ * Libraries API looks in the following directories for libraries:
+ * - libraries
+ * - profiles/$profile/libraries
+ * - sites/all/libraries
+ * - sites/$site/libraries
+ * This hook allows you to specify additional locations to look for libraries.
+ * This should only be used in advanced use-cases, the above directories should
+ * almost always suffice.
+ *
+ * @return
+ *   An array of library paths.
+ */
+function hook_libraries_paths() {
+  // Libraries residing in a module directory are strongly discouraged. The
+  // following is only used in the Libraries Test module for the testing
+  // framework to find the library.
+  return array(drupal_get_path('module', 'libraries_test'));
+}
Index: libraries.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/libraries/libraries.module,v
retrieving revision 1.6
diff -u -p -r1.6 libraries.module
--- libraries.module	23 Jul 2010 12:57:01 -0000	1.6
+++ libraries.module	28 Sep 2010 21:04:33 -0000
@@ -92,26 +92,51 @@ function libraries_get_libraries() {
     $searchdir[] = "$config/$directory";
   }
 
+  // Allow modules to define additional library paths.
+  $searchdir = array_merge($searchdir, module_invoke_all('libraries_paths'));
+
   // Retrieve list of directories.
   // @todo Core: Allow to scan for directories.
   $directories = array();
-  $nomask = array('CVS');
   foreach ($searchdir as $dir) {
-    if (is_dir($dir) && $handle = opendir($dir)) {
-      while (FALSE !== ($file = readdir($handle))) {
-        if (!in_array($file, $nomask) && $file[0] != '.') {
-          if (is_dir("$dir/$file")) {
-            $directories[$file] = "$dir/$file";
-          }
+    $directories += _libraries_scan_directory($dir);
+  }
+
+  return $directories;
+}
+
+
+/**
+ * Scans a directory.
+ *
+ * Recursively scans for all child directories in a given parent directory.
+ *
+ * @param $dir
+ *   A directory to search.
+ *
+ * @return
+ *   An array of directories keyed by the name of the final directory in the
+ *   path.
+ */
+function _libraries_scan_directory($dir) {
+  $nomask = array('CVS');
+  $directories = array();
+  if (is_dir($dir) && $handle = opendir($dir)) {
+    while (FALSE !== ($file = readdir($handle))) {
+      if (!in_array($file, $nomask) && $file[0] != '.') {
+        if (is_dir("$dir/$file")) {
+          $directories[$file] = "$dir/$file";
+          // Scan directories recursively.
+          $directories += _libraries_scan_directory("$dir/$file");
         }
       }
-      closedir($handle);
     }
+    closedir($handle);
   }
-
   return $directories;
 }
 
+
 /**
  * Returns information about registered libraries.
  *
@@ -136,27 +161,37 @@ function libraries_info($library = NULL)
 
   if (!isset($libraries)) {
     $libraries = array();
+    // Gather information from hook_libraries_info().
     foreach (module_implements('libraries_info') as $module) {
       foreach (module_invoke($module, 'libraries_info') as $name => $properties) {
         $properties['module'] = $module;
         $properties['name'] = $name;
-
-        $properties += array(
-          'title' => $name,
-          'vendor url' => '',
-          'download url' => '',
-          'path' => '',
-          'version callback' => 'libraries_get_version',
-          'version arguments' => array(),
-          'files' => array(),
-          'variants' => array(),
-          'versions' => array(),
-          'integration files' => array(),
-        );
-
         $libraries[$name] = $properties;
       }
     }
+    // Gather information from .info files.
+    foreach (libraries_get_libraries() as $directory => $path) {
+      $file = "$path/$directory.info";
+      if (file_exists($file)) {
+        $libraries[$directory] = drupal_parse_info_file($file);
+        $libraries[$directory]['library path'] = $path;
+      }
+    }
+    // Provide defaults.
+    foreach ($libraries as $name => &$properties) {
+      $properties += array(
+        'title' => $name,
+        'vendor url' => '',
+        'download url' => '',
+        'path' => '',
+        'version callback' => 'libraries_get_version',
+        'version arguments' => array(),
+        'files' => array(),
+        'variants' => array(),
+        'versions' => array(),
+        'integration files' => array(),
+      );
+    }
     // Allow modules to alter the registered libraries.
     drupal_alter('libraries_info', $libraries);
   }
Index: tests/libraries.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/libraries/tests/libraries.test,v
retrieving revision 1.4
diff -u -p -r1.4 libraries.test
--- tests/libraries.test	22 Sep 2010 17:00:56 -0000	1.4
+++ tests/libraries.test	28 Sep 2010 21:04:34 -0000
@@ -26,6 +26,23 @@ class LibrariesTestCase extends DrupalWe
    * @todo Better method name(s); split into detection/loading/overloading/etc.
    */
   public function testLibraries() {
+    // Test a library specified with an .info file.
+    $library = libraries_info('example');
+    $expected = array(
+      'library path' => drupal_get_path('module', 'libraries_test') . '/example',
+      'title' => 'example',
+      'vendor url' => '',
+      'download url' => '',
+      'path' => '',
+      'version callback' => 'libraries_get_version',
+      'version arguments' => array(),
+      'files' => array(),
+      'variants' => array(),
+      'versions' => array(),
+      'integration files' => array(),
+    );
+    $this->assertEqual($library, $expected, 'Library specified with an .info file found');
+
     // Test missing library.
     $library = libraries_info('example_missing');
     libraries_detect_library($library);
Index: tests/libraries_test.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/libraries/tests/libraries_test.module,v
retrieving revision 1.3
diff -u -p -r1.3 libraries_test.module
--- tests/libraries_test.module	22 Sep 2010 17:00:56 -0000	1.3
+++ tests/libraries_test.module	28 Sep 2010 21:04:34 -0000
@@ -288,6 +288,13 @@ function libraries_test_libraries_info()
 }
 
 /**
+ * Implements hook_libraries_paths().
+ */
+function libraries_test_libraries_paths() {
+  return array(drupal_get_path('module', 'libraries_test'));
+}
+
+/**
  * Gets the version of an example library.
  *
  * Returns exactly the version string entered as the $version parameter. This
