diff --git a/libraries.api.php b/libraries.api.php
index 66fa772..fa64b20 100644
--- a/libraries.api.php
+++ b/libraries.api.php
@@ -118,10 +118,14 @@
  *     - $variant: If the $library array belongs to a certain variant (see
  *       above), a string containing the variant name. NULL, otherwise.
  *     Valid callback groups are:
- *     - prepare: Callbacks registered in this group are applied as soon as the
+ *     - info: Callbacks registered in this group are applied as soon as the
  *       library information has been retrieved via hook_libraries_info() or
  *       info files.
- *     - detect: Callbacks registered in this group are applied as soon as
+ *     - pre detect: Callbacks registered in this group are applied when a
+ *       library is about to be detected, before the version callback is
+ *       invoked. At this point following additional information is available:
+ *       - $library['library path']: The path on the file system to the library.
+ *     - post detect: Callbacks registered in this group are applied as soon as
  *       library detection has been completed. At this point the library
  *       contains the version-specific information, if specified, and following
  *       additional information is available:
diff --git a/libraries.module b/libraries.module
index 192a052..0e8c647 100644
--- a/libraries.module
+++ b/libraries.module
@@ -155,7 +155,7 @@ function libraries_scan_info_files() {
  *
  * @param $group
  *   A string containing the group of callbacks that is to be applied. Should be
- *   either 'prepare', 'detect', or 'load'.
+ *   either 'info', 'pre detect', 'post detect', or 'load'.
  * @param $library
  *   An array of library information, passed by reference.
  */
@@ -244,34 +244,15 @@ function libraries_info($name = NULL) {
 
     // Provide defaults.
     foreach ($libraries as $machine_name => &$properties) {
-      $properties += array(
-        'machine name' => $machine_name,
-        'name' => $machine_name,
-        'vendor url' => '',
-        'download url' => '',
-        'path' => '',
-        'library path' => NULL,
-        'version callback' => 'libraries_get_version',
-        'version arguments' => array(),
-        'files' => array(),
-        'variants' => array(),
-        'versions' => array(),
-        'integration files' => array(),
-        'callbacks' => array(),
-      );
-      $properties['callbacks'] += array(
-        'prepare' => array(),
-        'detect' => array(),
-        'load' => array(),
-      );
+      libraries_info_defaults($properties, $machine_name);
     }
 
     // Allow modules to alter the registered libraries.
     drupal_alter('libraries_info', $libraries);
 
-    // Invoke callbacks in the 'prepare' group.
+    // Invoke callbacks in the 'info' group.
     foreach ($libraries as &$properties) {
-      libraries_invoke('prepare', $properties);
+      libraries_invoke('info', $properties);
     }
   }
 
@@ -282,6 +263,41 @@ function libraries_info($name = NULL) {
 }
 
 /**
+ * Applies default properties to a library definition.
+ *
+ * @param $library
+ *   An array of library information.
+ * @param $machine_name
+ *   The machine name of a library to return registered information for, or
+ *   FALSE if no library with the given name exists. If omitted, information
+ *   about all libraries is returned.
+ */
+function libraries_info_defaults(&$library, $machine_name) {
+  $library += array(
+    'machine name' => $machine_name,
+    'name' => $machine_name,
+    'vendor url' => '',
+    'download url' => '',
+    'path' => '',
+    'library path' => NULL,
+    'version callback' => 'libraries_get_version',
+    'version arguments' => array(),
+    'files' => array(),
+    'variants' => array(),
+    'versions' => array(),
+    'integration files' => array(),
+    'callbacks' => array(),
+  );
+  $library['callbacks'] += array(
+    'info' => array(),
+    'pre detect' => array(),
+    'post detect' => array(),
+    'load' => array(),
+  );
+  return $library;
+}
+
+/**
  * Tries to detect a library and its installed version.
  *
  * @todo We need to figure out whether, and if, how we want to retain the
@@ -313,101 +329,113 @@ function libraries_info($name = NULL) {
  * @see libraries_info()
  */
 function libraries_detect($name) {
-  $library = libraries_info($name);
+  $detected = &drupal_static(__FUNCTION__, array());
 
-  $library['installed'] = FALSE;
+  if (!isset($detected[$name])) {
+    $library = libraries_info($name);
 
-  // Check whether the library exists.
-  if (!isset($library['library path'])) {
-    $library['library path'] = libraries_get_path($library['machine name']);
-  }
-  if ($library['library path'] === FALSE || !file_exists($library['library path'])) {
-    $library['error'] = 'not found';
-    $library['error message'] = t('The %library library could not be found.', array(
-      '%library' => $library['name'],
-    ));
-    return $library;
-  }
+    $library['installed'] = FALSE;
 
-  // Detect library version, if not hardcoded.
-  if (!isset($library['version'])) {
-    // We support both a single parameter, which is an associative array, and an
-    // indexed array of multiple parameters.
-    if (isset($library['version arguments'][0])) {
-      // Add the library as the first argument.
-      $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments']));
+    // Check whether the library exists.
+    if (!isset($library['library path'])) {
+      $library['library path'] = libraries_get_path($library['machine name']);
     }
-    else {
-      $library['version'] = $library['version callback']($library, $library['version arguments']);
-    }
-    if (empty($library['version'])) {
-      $library['error'] = 'not detected';
-      $library['error message'] = t('The version of the %library library could not be detected.', array(
+    if ($library['library path'] === FALSE || !file_exists($library['library path'])) {
+      $library['error'] = 'not found';
+      $library['error message'] = t('The %library library could not be found.', array(
         '%library' => $library['name'],
       ));
-      return $library;
+      $detected[$name] = $library;
+      return $detected[$name];
     }
-  }
 
-  // Determine to which supported version the installed version maps.
-  if (!empty($library['versions'])) {
-    ksort($library['versions']);
-    $version = 0;
-    foreach ($library['versions'] as $supported_version => $version_properties) {
-      if (version_compare($library['version'], $supported_version, '>=')) {
-        $version = $supported_version;
+    // Invoke callbacks in the 'pre detect' group.
+    libraries_invoke('pre detect', $library);
+
+    // Detect library version, if not hardcoded.
+    if (!isset($library['version'])) {
+      // We support both a single parameter, which is an associative array, and an
+      // indexed array of multiple parameters.
+      if (isset($library['version arguments'][0])) {
+        // Add the library as the first argument.
+        $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments']));
+      }
+      else {
+        $library['version'] = $library['version callback']($library, $library['version arguments']);
+      }
+      if (empty($library['version'])) {
+        $library['error'] = 'not detected';
+        $library['error message'] = t('The version of the %library library could not be detected.', array(
+          '%library' => $library['name'],
+        ));
+        $detected[$name] = $library;
+        return $detected[$name];
       }
-    }
-    if (!$version) {
-      $library['error'] = 'not supported';
-      $library['error message'] = t('The installed version %version of the %library library is not supported.', array(
-        '%version' => $library['version'],
-        '%library' => $library['name'],
-      ));
-      return $library;
     }
 
-    // Apply version specific definitions and overrides.
-    $library = array_merge($library, $library['versions'][$version]);
-    unset($library['versions']);
-  }
-
-  // Check each variant if it is installed.
-  if (!empty($library['variants'])) {
-    foreach ($library['variants'] as $variant_name => &$variant) {
-      // If no variant callback has been set, assume the variant to be
-      // installed.
-      if (!isset($variant['variant callback'])) {
-        $variant['installed'] = TRUE;
+    // Determine to which supported version the installed version maps.
+    if (!empty($library['versions'])) {
+      ksort($library['versions']);
+      $version = 0;
+      foreach ($library['versions'] as $supported_version => $version_properties) {
+        if (version_compare($library['version'], $supported_version, '>=')) {
+          $version = $supported_version;
+        }
       }
-      else {
-        // We support both a single parameter, which is an associative array,
-        // and an indexed array of multiple parameters.
-        if (isset($variant['variant arguments'][0])) {
-          // Add the library as the first argument, and the variant name as the second.
-          $variant['installed'] = call_user_func_array($variant['variant callback'], array_merge(array($library, $variant_name), $variant['variant arguments']));
+      if (!$version) {
+        $library['error'] = 'not supported';
+        $library['error message'] = t('The installed version %version of the %library library is not supported.', array(
+          '%version' => $library['version'],
+          '%library' => $library['name'],
+        ));
+        $detected[$name] = $library;
+        return $detected[$name];
+      }
+
+      // Apply version specific definitions and overrides.
+      $library = array_merge($library, $library['versions'][$version]);
+      unset($library['versions']);
+    }
+
+    // Check each variant if it is installed.
+    if (!empty($library['variants'])) {
+      foreach ($library['variants'] as $variant_name => &$variant) {
+        // If no variant callback has been set, assume the variant to be
+        // installed.
+        if (!isset($variant['variant callback'])) {
+          $variant['installed'] = TRUE;
         }
         else {
-          $variant['installed'] = $variant['variant callback']($library, $variant_name, $variant['variant arguments']);
-        }
-        if (!$variant['installed']) {
-          $variant['error'] = 'not found';
-          $variant['error message'] = t('The %variant variant of the %library library could not be found.', array(
-            '%variant' => $variant_name,
-            '%library' => $library['name'],
-          ));
+          // We support both a single parameter, which is an associative array,
+          // and an indexed array of multiple parameters.
+          if (isset($variant['variant arguments'][0])) {
+            // Add the library as the first argument, and the variant name as the second.
+            $variant['installed'] = call_user_func_array($variant['variant callback'], array_merge(array($library, $variant_name), $variant['variant arguments']));
+          }
+          else {
+            $variant['installed'] = $variant['variant callback']($library, $variant_name, $variant['variant arguments']);
+          }
+          if (!$variant['installed']) {
+            $variant['error'] = 'not found';
+            $variant['error message'] = t('The %variant variant of the %library library could not be found.', array(
+              '%variant' => $variant_name,
+              '%library' => $library['name'],
+            ));
+          }
         }
       }
     }
-  }
 
-  // If we end up here, the library should be usable.
-  $library['installed'] = TRUE;
+    // If we end up here, the library should be usable.
+    $library['installed'] = TRUE;
 
-  // Invoke callbacks in the 'detect' group.
-  libraries_invoke('detect', $library);
+    // Invoke callbacks in the 'post detect' group.
+    libraries_invoke('post detect', $library);
 
-  return $library;
+    $detected[$name] = $library;
+  }
+
+  return $detected[$name];
 }
 
 /**
diff --git a/tests/libraries.test b/tests/libraries.test
index b9521ef..0967831 100644
--- a/tests/libraries.test
+++ b/tests/libraries.test
@@ -141,8 +141,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
     $this->assertEqual($library['variants']['example_variant']['installed'], TRUE, 'Existing variant found.');
 
     // Test the applying of callbacks.
-    $expected = array_merge(libraries_info('example_empty'), array(
-      'machine name' => 'example_callback',
+    $expected = array(
       'name' => 'Example callback',
       'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
       'version' => '1',
@@ -150,69 +149,96 @@ class LibrariesTestCase extends DrupalWebTestCase {
         '1' => array(
           'variants' => array(
             'example_variant' => array(
-              'prepare callback' => 'not applied',
-              'detect callback' => 'not applied',
+              'info callback' => 'not applied',
+              'pre detect callback' => 'not applied',
+              'post detect callback' => 'not applied',
               'load callback' => 'not applied',
             ),
           ),
-          'prepare callback' => 'not applied',
-          'detect callback' => 'not applied',
+          'info callback' => 'not applied',
+          'pre detect callback' => 'not applied',
+          'post detect callback' => 'not applied',
           'load callback' => 'not applied',
         ),
       ),
       'variants' => array(
         'example_variant' => array(
-          'prepare callback' => 'not applied',
-          'detect callback' => 'not applied',
+          'info callback' => 'not applied',
+          'pre detect callback' => 'not applied',
+          'post detect callback' => 'not applied',
           'load callback' => 'not applied',
         ),
       ),
       'callbacks' => array(
-        'prepare' => array('_libraries_test_prepare_callback'),
-        'detect' => array('_libraries_test_detect_callback'),
+        'info' => array('_libraries_test_info_callback'),
+        'pre detect' => array('_libraries_test_pre_detect_callback'),
+        'post detect' => array('_libraries_test_post_detect_callback'),
         'load' => array('_libraries_test_load_callback'),
       ),
-      'prepare callback' => 'not applied',
-      'detect callback' => 'not applied',
+      'info callback' => 'not applied',
+      'pre detect callback' => 'not applied',
+      'post detect callback' => 'not applied',
       'load callback' => 'not applied',
-    ));
-    // Test a callback in the 'prepare' phase.
-    $expected['prepare callback'] = 'applied (top-level)';
-    $expected['versions']['1']['prepare callback'] = 'applied (version 1)';
-    $expected['versions']['1']['variants']['example_variant']['prepare callback'] = 'applied (version 1, variant example_variant)';
-    $expected['variants']['example_variant']['prepare callback'] = 'applied (variant example_variant)';
+      'module' => 'libraries_test',
+    );
+    libraries_info_defaults($expected, 'example_callback');
+
+    // Test a callback in the 'info' phase.
+    $expected['info callback'] = 'applied (top-level)';
+    $expected['versions']['1']['info callback'] = 'applied (version 1)';
+    $expected['versions']['1']['variants']['example_variant']['info callback'] = 'applied (version 1, variant example_variant)';
+    $expected['variants']['example_variant']['info callback'] = 'applied (variant example_variant)';
+
     $library = libraries_info('example_callback');
-    $this->verbose(var_export($expected, TRUE));
-    $this->verbose(var_export($library, TRUE));
-    $this->assertEqual($library, $expected, 'Prepare callback was applied correctly.');
-    // Test a callback in the 'detect' phase.
+    $this->verbose('Expected:<pre>' . var_export($expected, TRUE) . '</pre>');
+    $this->verbose('Actual:<pre>' . var_export($library, TRUE) . '</pre>');
+    $this->assertEqual($library, $expected, 'Info callback was applied correctly.');
+
+    // Test a callback in the 'pre detect' and 'post detect' phases.
+    // Successfully detected libraries should only contain version information
+    // for the detected version and thus, be marked as installed.
     unset($expected['versions']);
     $expected['installed'] = TRUE;
-    $expected['prepare callback'] = 'applied (version 1)';
+
+    // Additionally, version-specific properties of the detected version are
+    // supposed to override the corresponding top-level properties.
+    $expected['info callback'] = 'applied (version 1)';
+    $expected['pre detect callback'] = 'applied (version 1)';
+    $expected['post detect callback'] = 'applied (top-level)';
     $expected['variants']['example_variant']['installed'] = TRUE;
-    $expected['variants']['example_variant']['prepare callback'] = 'applied (version 1, variant example_variant)';
-    $expected['detect callback'] = 'applied (top-level)';
-    $expected['variants']['example_variant']['detect callback'] = 'applied (variant example_variant)';
+    $expected['variants']['example_variant']['info callback'] = 'applied (version 1, variant example_variant)';
+    $expected['variants']['example_variant']['pre detect callback'] = 'applied (version 1, variant example_variant)';
+    $expected['variants']['example_variant']['post detect callback'] = 'applied (variant example_variant)';
+
     $library = libraries_detect('example_callback');
-    $this->verbose(var_export($expected, TRUE));
-    $this->verbose(var_export($library, TRUE));
-    $this->assertEqual($library, $expected, 'Detect callback was applied correctly.');
+    $this->verbose('Expected:<pre>' . var_export($expected, TRUE) . '</pre>');
+    $this->verbose('Actual:<pre>' . var_export($library, TRUE) . '</pre>');
+    $this->assertEqual($library, $expected, 'Pre and post detect callbacks were applied correctly.');
 
     // Test a callback in the 'load' phase.
+    // Successfully loaded libraries should only contain information about the
+    // already loaded variant.
     unset($expected['variants']);
     $expected['loaded'] = 0;
     $expected['load callback'] = 'applied (top-level)';
+
     $library = libraries_load('example_callback');
-    $this->verbose(var_export($expected, TRUE));
-    $this->verbose(var_export($library, TRUE));
+    $this->verbose('Expected:<pre>' . var_export($expected, TRUE) . '</pre>');
+    $this->verbose('Actual:<pre>' . var_export($library, TRUE) . '</pre>');
     $this->assertEqual($library, $expected, 'Load callback was applied correctly.');
+
     // This is not recommended usually and is only used for testing purposes.
     drupal_static_reset('libraries_load');
-    $expected['prepare callback'] = 'applied (version 1, variant example_variant)';
-    $expected['detect callback'] = 'applied (variant example_variant)';
+
+    // Successfully loaded library variants are supposed to contain the specific
+    // variant information only.
+    $expected['info callback'] = 'applied (version 1, variant example_variant)';
+    $expected['pre detect callback'] = 'applied (version 1, variant example_variant)';
+    $expected['post detect callback'] = 'applied (variant example_variant)';
+
     $library = libraries_load('example_callback', 'example_variant');
-    $this->verbose(var_export($expected, TRUE));
-    $this->verbose(var_export($library, TRUE));
+    $this->verbose('Expected:<pre>' . var_export($expected, TRUE) . '</pre>');
+    $this->verbose('Actual:<pre>' . var_export($library, TRUE) . '</pre>');
     $this->assertEqual($library, $expected, 'Load callback was applied correctly to a variant.');
 
     // Test loading of a simple library with a top-level files property.
diff --git a/tests/libraries_test.module b/tests/libraries_test.module
index bf1369f..545ab43 100644
--- a/tests/libraries_test.module
+++ b/tests/libraries_test.module
@@ -210,33 +210,38 @@ function libraries_test_libraries_info() {
         'variants' => array(
           'example_variant' => array(
             // These keys are for testing purposes only.
-            'prepare callback' => 'not applied',
-            'detect callback' => 'not applied',
+            'info callback' => 'not applied',
+            'pre detect callback' => 'not applied',
+            'post detect callback' => 'not applied',
             'load callback' => 'not applied',
           ),
         ),
         // These keys are for testing purposes only.
-        'prepare callback' => 'not applied',
-        'detect callback' => 'not applied',
+        'info callback' => 'not applied',
+        'pre detect callback' => 'not applied',
+        'post detect callback' => 'not applied',
         'load callback' => 'not applied',
       ),
     ),
     'variants' => array(
       'example_variant' => array(
         // These keys are for testing purposes only.
-        'prepare callback' => 'not applied',
-        'detect callback' => 'not applied',
+        'info callback' => 'not applied',
+        'pre detect callback' => 'not applied',
+        'post detect callback' => 'not applied',
         'load callback' => 'not applied',
       ),
     ),
     'callbacks' => array(
-      'prepare' => array('_libraries_test_prepare_callback'),
-      'detect' => array('_libraries_test_detect_callback'),
+      'info' => array('_libraries_test_info_callback'),
+      'pre detect' => array('_libraries_test_pre_detect_callback'),
+      'post detect' => array('_libraries_test_post_detect_callback'),
       'load' => array('_libraries_test_load_callback'),
     ),
     // These keys are for testing purposes only.
-    'prepare callback' => 'not applied',
-    'detect callback' => 'not applied',
+    'info callback' => 'not applied',
+    'pre detect callback' => 'not applied',
+    'post detect callback' => 'not applied',
     'load callback' => 'not applied',
   );
 
@@ -326,61 +331,42 @@ function _libraries_test_return_installed($library, $name, $installed) {
 }
 
 /**
- * Sets the 'prepare callback' key.
+ * Sets the 'info callback' key.
  *
- * This function is used as a test callback for the 'prepare' callback group.
- *
- * @param $library
- *   An array of library information, which may be version- or variant-specific.
- *   Passed by reference.
- * @param $version
- *   The version the library information passed in $library belongs to, or NULL
- *   if the passed library information is not version-specific.
- * @param $variant
- *   The variant the library information passed in $library belongs to, or NULL
- *   if the passed library information is not variant-specific.
+ * This is used as a test callback for the 'info' callback group.
  *
  * @see _libraries_test_callback()
  */
-function _libraries_test_prepare_callback(&$library, $version, $variant) {
-  _libraries_test_callback($library, $version, $variant, 'prepare');
+function _libraries_test_info_callback(&$library, $version, $variant) {
+  _libraries_test_callback($library, $version, $variant, 'info');
 }
 
 /**
- * Sets the 'detect callback' key.
+ * Sets the 'pre detect callback' key.
  *
- * This function is used as a test callback for the 'detect' callback group.
+ * This is used as a test callback for the 'pre detect' callback group.
  *
- * @param $library
- *   An array of library information, which may be version- or variant-specific.
- *   Passed by reference.
- * @param $version
- *   The version the library information passed in $library belongs to, or NULL
- *   if the passed library information is not version-specific.
- * @param $variant
- *   The variant the library information passed in $library belongs to, or NULL
- *   if the passed library information is not variant-specific.
+ * @see _libraries_test_callback()
+ */
+function _libraries_test_pre_detect_callback(&$library, $version, $variant) {
+  _libraries_test_callback($library, $version, $variant, 'pre detect');
+}
+
+/**
+ * Sets the 'post detect callback' key.
+ *
+ * This is used as a test callback for the 'post detect' callback group.
  *
  * @see _libraries_test_callback()
  */
-function _libraries_test_detect_callback(&$library, $version, $variant) {
-  _libraries_test_callback($library, $version, $variant, 'detect');
+function _libraries_test_post_detect_callback(&$library, $version, $variant) {
+  _libraries_test_callback($library, $version, $variant, 'post detect');
 }
 
 /**
  * Sets the 'load callback' key.
  *
- * This function is used as a test callback for the 'load' callback group.
- *
- * @param $library
- *   An array of library information, which may be version- or variant-specific.
- *   Passed by reference.
- * @param $version
- *   The version the library information passed in $library belongs to, or NULL
- *   if the passed library information is not version-specific.
- * @param $variant
- *   The variant the library information passed in $library belongs to, or NULL
- *   if the passed library information is not variant-specific.
+ * This is used as a test callback for the 'load' callback group.
  *
  * @see _libraries_test_callback()
  */
@@ -389,7 +375,9 @@ function _libraries_test_load_callback(&$library, $version, $variant) {
 }
 
 /**
- * Sets the '[group] callback' key, where [group] is prepare, detect, or load.
+ * Sets the '[group] callback' key.
+ *
+ * [group] can be info, pre detect, post detect, or load.
  *
  * This function is used as a test callback for the all callback groups.
  *
