Index: features.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/features/features.module,v
retrieving revision 1.1.2.63.2.8
diff -u -r1.1.2.63.2.8 features.module
--- features.module	17 Sep 2010 21:03:26 -0000	1.1.2.63.2.8
+++ features.module	22 Sep 2010 15:59:42 -0000
@@ -400,44 +400,33 @@
 }
 
 /**
- * Like module_invoke() but for arbitrary callback base names.
+ * Invoke a component callback.
  */
-function features_invoke() {
+function features_invoke($component, $callback) {
   $args = func_get_args();
-  $base = $args[0];
-  $hook = $args[1];
   unset($args[0], $args[1]);
-  $function = $base . '_' . $hook;
-  if (features_hook($base, $hook)) {
+  // Append the component name to the arguments.
+  $args[] = $component;
+  if ($function = features_hook($component, $callback)) {
     return call_user_func_array($function, $args);
   }
 }
 
 /**
- * Like module_invoke_all() but for arbitrary callback base names.
+ * Checks whether a component implements the given hook.
+ *
+ * @return
+ *   The function implementing the hook, or FALSE.
  */
-function features_invoke_all() {
-  $args = func_get_args();
-  $hook = $args[0];
-  unset($args[0]);
-  $return = array();
-  foreach (features_get_components() as $component => $info) {
-    $result = features_invoke($component, $hook);
-    if (isset($result) && is_array($result)) {
-      $return = array_merge_recursive($return, $result);
-    }
-    else if (isset($result)) {
-      $return[] = $result;
-    }
-  }
-  return $return;
-}
+function features_hook($component, $hook) {
+  $static = &drupal_static(__FUNCTION__);
 
-/**
- * Like module_hook() but for arbitrary callback base names.
- */
-function features_hook($base, $hook) {
-  return function_exists($base . '_' . $hook);
+  if (!isset($static)) {
+    $info = module_invoke_all('features_api');
+  }
+  // Determine the function callback base.
+  $base = isset($info[$component]['base']) ? $info[$component]['base'] : $component;
+  return function_exists($base . '_' . $hook) ? $base . '_' . $hook : FALSE;
 }
 
 /**
Index: features.export.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/features/features.export.inc,v
retrieving revision 1.1.2.47.2.9
diff -u -r1.1.2.47.2.9 features.export.inc
--- features.export.inc	21 Sep 2010 15:16:33 -0000	1.1.2.47.2.9
+++ features.export.inc	22 Sep 2010 15:59:41 -0000
@@ -44,10 +44,9 @@
 function _features_populate($pipe, &$export, $module_name = '') {
   features_include();
   foreach ($pipe as $component => $data) {
-    if (features_hook($component, 'features_export')) {
+    if ($function = features_hook($component, 'features_export')) {
       // Pass module-specific data and export array.
       // We don't use features_invoke() here since we need to pass $export by reference.
-      $function = "{$component}_features_export";
       $more = $function($data, $export, $module_name);
       // Allow other modules to manipulate the pipe to add in additional modules.
       drupal_alter('features_pipe_' . $component, $more, $data, $export);
@@ -389,7 +388,7 @@
     sprintf("%11s", decoct(REQUEST_TIME)) // Creation time
   );
   $binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", '', '', '', '', '', '', '', '', '', '');
-  
+
   $checksum = 0;
   for ($i = 0; $i < 148; $i++) {
     $checksum += ord(substr($binary_data_first, $i, 1));
@@ -400,11 +399,11 @@
   for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
     $checksum += ord(substr($binary_data_last, $j, 1));
   }
-  
+
   $tar .= $binary_data_first;
   $tar .= pack("a8", sprintf("%6s ", decoct($checksum)));
   $tar .= $binary_data_last;
-  
+
   $buffer = str_split($contents, 512);
   foreach ($buffer as $item) {
     $tar .= pack("a512", $item);
